How to properly handle NSFileHandle exceptions in Swift 2.0?

前端 未结 3 651
天涯浪人
天涯浪人 2020-12-29 06:02

First of all, I am new to iOS and Swift and come from a background of Android/Java programming. So to me the idea of catching an exception from an attempt to write to a file

相关标签:
3条回答
  • 2020-12-29 06:31

    a second (recoverable) solution would be to create a very simple ObjectiveC++ function that takes a block and returns an exception.

    create a file entitled: ExceptionCatcher.h and add import it in your bridging header (Xcode will prompt to create one for you if you don't have one already)

    //
    //  ExceptionCatcher.h
    //
    
    #import <Foundation/Foundation.h>
    
    NS_INLINE NSException * _Nullable tryBlock(void(^_Nonnull tryBlock)(void)) {
        @try {
            tryBlock();
        }
        @catch (NSException *exception) {
            return exception;
        }
        return nil;
    }
    

    Using this helper is quite simple, I have adapted my code from above to use it.

    func appendString(string: String, filename: String) -> Bool {
        guard let fileHandle = NSFileHandle(forUpdatingAtPath: filename) else { return false }
        guard let data = string.dataUsingEncoding(NSUTF8StringEncoding) else { return false }
    
        // will cause seekToEndOfFile to throw an excpetion
        fileHandle.closeFile()
    
        let exception = tryBlock {
            fileHandle.seekToEndOfFile()
            fileHandle.writeData(data)
        }
        print("exception: \(exception)")
    
        return exception == nil
    }
    
    0 讨论(0)
  • 2020-12-29 06:46

    seekToEndOfFile() and writeData() are not marked as throws (they don't throw an NSError object which can be caught in with a do-try-catch block), which means in the current state of Swift, the NSExceptions raised by them cannot be "caught".

    If you're working on a Swift project, you could create an Objective-C class which implements your NSFileHandle methods that catches the NSExceptions (like in this question), but otherwise you're out of luck.

    0 讨论(0)
  • 2020-12-29 06:47

    This can be achieved without using Objective C code, here is a complete example.

    class SomeClass: NSObject {
        static func appendString(string: String, filename: String) -> Bool {
            guard let fileHandle = NSFileHandle(forUpdatingAtPath: filename) else { return false }
            guard let data = string.dataUsingEncoding(NSUTF8StringEncoding) else { return false }
    
            // will cause seekToEndOfFile to throw an excpetion
            fileHandle.closeFile()
    
            SomeClass.startHandlingExceptions()
            fileHandle.seekToEndOfFile()
            fileHandle.writeData(data)
            SomeClass.stopHandlingExceptions()
    
            return true
        }
    
        static var existingHandler: (@convention(c) NSException -> Void)?
        static func startHandlingExceptions() {
            SomeClass.existingHandler = NSGetUncaughtExceptionHandler()
            NSSetUncaughtExceptionHandler({ exception in
                print("exception: \(exception))")
                SomeClass.existingHandler?(exception)
            })
        }
    
        static func stopHandlingExceptions() {
            NSSetUncaughtExceptionHandler(SomeClass.existingHandler)
            SomeClass.existingHandler = nil
        }
    }
    

    Call SomeClass.appendString("add me to file", filename:"/some/file/path.txt") to run it.

    0 讨论(0)
提交回复
热议问题