How to handle exceptions happened in readData(ofLength)?

Apple offered two ways of reading data from FileHandle():

// till macOS 10.15.3

func readData(ofLength length: Int) -> Data

// macOS 10.15.4 and later

func read(upToCount count: Int) throws -> Data?

For some reasons I have to use the previous one (to make sure it works with older macOS releases).

However, the first choice doesn't throw fileHandleOperationException by default.

Is there a way to let it return nil on fileHandleOperationException?

Answered by DTS Engineer in 740987022

For some reasons I have to use the previous one (to make sure it works with older macOS releases).

There’s no safe way to call the legacy method from Swift (which is why we added the new one). If you need to support older OS releases, I see a couple of options:

  • Use a different file system API.

  • Write an Objective-C wrapper that calls the old method and handles any thrown exception [1].

Note that, in general, Objective-C exceptions are meant to be fatal. That is, it’s not safe for you to catch an exception and continue with the normal execution of your program. NSFileHandle is a specific exception (hey hey) to this rule. Catching and continuing after such an exception is fine.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] Here’s an example of what that might look like:

@implementation NSFileHandle (QAdditions)

- (nullable NSData *)qqq_readUpToCount:(NSInteger)count error:(NSError * __autoreleasing * _Nullable)errorPtr {
    NSParameterAssert(count >= 0);
    @try {
        return [self readDataOfLength: (NSUInteger) count];
    }
    @catch (NSError * error) {
        if (errorPtr != nil) {
            *errorPtr = error;
        }
        return nil;
    }
}

@end

IMPORTANT This compiles but I’ve not actually tested it.

Accepted Answer

For some reasons I have to use the previous one (to make sure it works with older macOS releases).

There’s no safe way to call the legacy method from Swift (which is why we added the new one). If you need to support older OS releases, I see a couple of options:

  • Use a different file system API.

  • Write an Objective-C wrapper that calls the old method and handles any thrown exception [1].

Note that, in general, Objective-C exceptions are meant to be fatal. That is, it’s not safe for you to catch an exception and continue with the normal execution of your program. NSFileHandle is a specific exception (hey hey) to this rule. Catching and continuing after such an exception is fine.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] Here’s an example of what that might look like:

@implementation NSFileHandle (QAdditions)

- (nullable NSData *)qqq_readUpToCount:(NSInteger)count error:(NSError * __autoreleasing * _Nullable)errorPtr {
    NSParameterAssert(count >= 0);
    @try {
        return [self readDataOfLength: (NSUInteger) count];
    }
    @catch (NSError * error) {
        if (errorPtr != nil) {
            *errorPtr = error;
        }
        return nil;
    }
}

@end

IMPORTANT This compiles but I’ve not actually tested it.

How to handle exceptions happened in readData(ofLength)?
 
 
Q