Many methods in Core Data’s NSManagedObjectContext uses this pattern, so lets use that as an example. First the method signature indicates that it requires a reference to an NSError pointer (rather than a pointer’s value). This is accomplished by placing two asterisks after the parameter type, instead of a single asterisk. For example the save method of NSManagedObjectContext accepts a reference to a pointer for an NSError (note the two asterisks after the type):
- (BOOL)save:(NSError **)error
The caller creates an NSError pointer whose initial value is ‘nil.’ A reference to this pointer is passed into the method by using the ‘&’ operator. If anything goes wrong, an NSError object would be created and assigned to the original pointer.
NSError *error; // Error is nil [managedObjectContext save:&error]; if( error ){ // Error is not nil - handle the issue } else { // Error is still nil - proceed with business logic }
Swift to Objective-C
Swift includes quite a bit of mapping to Objective-C objects for us, and NSError** is no exception (sorry… pun intended). The mapping used between NSError** and Swift is called AutoreleasingUnsafeMutablePointer<NSError?> (though a more ‘readable’ typealias is used: NSErrorPointer). So whenever you see a method signature that requires an NSErrorPointer parameter, use the ‘&’ operator just as you did with Objective-C. For example the Swift version of the “save” method signature looks like this:
func save(_ error: NSErrorPointer) -> Bool
A call to this method would look like:
var error: NSError? = nil managedObjectContext?.save(&error) if let theError = error { // Error is not nil - handle the issue } else { // Error is still nil - proceed with business logic. }
In-Out Parameters
Unless you are going to be mapping Swift to Objective-C code, you can use a simpler syntax for methods that require a reference to a variable: in-out parameters. An in-out parameter is any parameter that has the keyword inout in front of it. For example, to change the the original value of a String that is passed into a method, you could do the following:
func changeOriginalString(inout theStr: String) { theStr += "!!!" } var originalString = "Hello" changeOriginalString(&originalString) println(originalString) // Prints: Hello!!!
In summary: whenever you see an NSErrorPointer, treat it just as you would an NSError** (use the ‘&’ operator on the argument). If you want to make your own Swift methods, which accept references to variables, define one or more “in-out” parameters. Just like an NSErrorPointer, have the caller use the ‘&’ operator on each in-out argument.