In a macOS programming project I have a command that allows the user to open a file containing some configuration options. This file is a property list, so the contents were being read using NSDictionary(contentsOf:)
; this method simply returns nil
if an error occurs. I wanted to provide more details about the failure than simply “The file could not be read”, so I looked for a Foundation method that would throw an NSError. I settled on FileHandle(forReadingFrom:)
and inserted the following code:
do { _ = try FileHandle(forReadingFrom: url) } catch let error as NSError { let alert = NSAlert() alert.messageText = "An error occurred while reading the options file.".localized() alert.informativeText = error.localizedDescription alert.beginSheetModal(for: mainWindow) { (response) in if response == NSAlertSecondButtonReturn { OperationQueue.main.addOperation { self.resetOptions(nil) } } } return }
Then I set up a few test cases, including a file that was owned by another user (with no read permission). To my surprise, the error description implied that I was unable to write the file:
[application icon redacted]
…and while that’s also true, that’s certainly not the error I expected to get.
I looked at the error object in the debugger, and sure enough, the error code was 513 (NSFileWriteNoPermissionError
) and not 257 (NSFileReadNoPermissionError
). Weird.
Well, I know I’m trying to read the file, and I don’t want to confuse the user, so I changed the catch
clause to handle this case:
catch var error as NSError { if error.code == NSFileWriteNoPermissionError { error = NSError(domain: NSCocoaErrorDomain, code: NSFileReadNoPermissionError, userInfo: error.userInfo) } let alert = NSAlert() //... return }
…and that seemed to do nicely. But I can’t find any documentation on whether this is expected behavior or what I might be doing wrong.
Comments closed