Let's say that you have a function like this:
func getSomething(error: NSErrorPointer) -> Something
and you typically use it this way:
var error : NSError? = nil
let a = getSomething(&error)
What is an idiomatic way to check for error here? More specific questions:
- If
error == nil
can we assume that a
will never be nil and vice
versa?
- What should we check first:
error
(for its nilness) or a
(to
confirm that it's not a nil)?
- Can
a != nil && error != nil
be true in some cases?
Thank you!
Compare Handling Error Objects Returned From Methods
in the "Error Handling Programming Guide":
Important: Success or failure is indicated by the return value of the
method. Although Cocoa methods that indirectly return error objects in
the Cocoa error domain are guaranteed to return such objects if the
method indicates failure by directly returning nil or NO, you should
always check that the return value is nil or NO before attempting to
do anything with the NSError object.
So for Cocoa/Cocoa Touch methods you should always check the return
value first. It is guaranteed that error != nil
if the method fails,
but it is not explicitly guaranteed that error == nil
if the method succeeds.
Examples:
JSON Serialization
var error : NSError?
if let jsonObj = NSJSONSerialization.JSONObjectWithData(jsonData, options: nil, error: &error) {
// success
} else {
// failure
println("Invalid JSON data: \(error!.localizedDescription)")
}
Core Data fetch request
var error : NSError?
if let result = context.executeFetchRequest(request, error: &error) {
// success, result has zero or more elements
} else {
// failure
println("Fetch failed: \(error!.localizedDescription)")
}
Copying files
var error : NSError?
if !NSFileManager.defaultManager().copyItemAtPath(srcPath, toPath: dstPath, error: &error) {
println("Cannot copy file: \(error!.localizedDescription)")
}
Of course you can define your own rules for your own functions,
but I would follow the same Apple guidelines.
Update: As of Swift 2, Cocoa methods that produce errors are
translated to Swift functions that throw an error, and this error
must be handled with try
-catch
. Here is the Swift 2 version
of above examples:
JSON Serialization
do {
let jsonObj = try NSJSONSerialization.JSONObjectWithData(jsonData, options: [])
// success
} catch let error as NSError {
// failure
print("Invalid JSON data: \(error.localizedDescription)")
}
Core Data fetch request
do {
let result = try context.executeFetchRequest(request)
// success, result has zero or more elements
} catch let error as NSError {
// failure
print("Fetch failed: \(error.localizedDescription)")
}
Copying files
do {
try NSFileManager.defaultManager().copyItemAtPath(srcPath, toPath: dstPath)
} catch let error as NSError {
print("Cannot copy file: \(error.localizedDescription)")
}
if a function returns an optional value i.e
func someFunc(someVar: String) -> NSData? {
// some code
}
(the optional means that it can return a nil)
then error checking is pretty simple
if let data = someFunc("someString") {
// this means there was NO error as the function didn't return a nil
}
else {
// This means there was an error
}
This video is a pretty good reference for error checking and handling in swift https://youtu.be/m8szaLqHVDs