Brief Intro to NSError of Foundation Framework
2013-11-23 11:46
417 查看
NSError
The Foundation Framework NSError class is
used to create error objects. The properties of this class are an error code, the error domain, and a dictionary of user information. The class includes methods
for creating and initializing error objects, retrieving error properties, getting a localized error description, and facilitating error recovery.
An error domain is a mechanism used to organize error codes according to a system, subsystem, framework,
and so forth. Error domains enable you to identify the subsystem, framework, and so forth, that detected the error. They also help prevent naming collisions between error codes, because error codes between different domains can have the same value.
The user info dictionary is anNSDictionary instance that holds error information beyond the code
and domain. The types of information that can be stored in this dictionary include localized error information and references to supporting objects. The following statement creates an error object using the NSError class
factory method errorWithDomain:code:userInfo:.
This particular error would be created if, for example, a file is not found at the path specified. Notice that the user info dictionary is not provided (the userInfo parameter
is set to nil). Listing
14-1creates the same error object, this time with a user info dictionary.
Listing
14-1. Creating an NSError Object
Listing 14-1 shows
the user info dictionary for this example consists of one entry, the key-value pair for a localized description. The localized string is created using the Foundation NSLocalizedStringfunction.
The constant NSLocalizedDescriptionKey is
a standard user info dictionary key defined in the NSError class.
The Foundation Framework declares four major error domains:
NSMachErrorDomain: OS kernel error codes.
NSPOSIXErrorDomain: Error codes derived from standard POSIX-conforming versions of Unix,
such as BSD.
NSOSStatusErrorDomain: Error codes specific to Apple OS X Core Services and the Carbon framework.
NSCocoaErrorDomain: All of the error codes for the Cocoa frameworks (this includes the Foundation
Framework and other Objective-C frameworks).
In addition to the major error domains presented here, there are also error domains for frameworks, groups of classes, and even individual classes. The NSError class
also enables you to create your own error domain when creating and initializing an NSError object. As mentioned previously, Listing
14-1uses the constant NSLocalizedDescriptionKey. The NSError class
defines a set of common user info dictionary keys that can be used to create the key-value pairs
for the user info dictionary. These keys are listed in Table
14-1.
Table
14-1. NSError Standard User Info Dictionary Keys
Using Error Objects
OK, so now you know how to create NSError objects, but how do you use them? In
general, there are two scenarios for obtaining NSError objects:
Delegation: An error object passed as a parameter to a delegation method that you implement.
Indirection: An error object retrieved via indirection from a method that your code invokes.
The delegation pattern is a design pattern whereby an object (the delegator) delegates one or more
tasks to another delegate object. The tasks are encapsulated in the method(s) of the delegate object. When necessary, the delegator invokes the appropriate method on the delegate object, providing any required parameters. Many Foundation Framework
classes implement the delegation pattern to enable custom error handling. The delegating Foundation object invokes a method on a delegate object (custom code that you implement) that includes an error object as a parameter.
The NSURLConnectionDelegate protocol declares a delegation method (connection:didFailWithError:)
that returns an error object:
This protocol is used for asynchronously loading a URL request via an NSURLConnection object.
Your code implements a delegate object that conforms to this protocol and sets it as the delegate of theNSURLConnection object.
Your code then loads the URL request asynchronously, and if an error occurs, the delegating (NSURLConnection)
object invokes the connection:didFailWithError:method
on your delegate object.
A common Objective-C programming convention for methods that return an error object is
to make this the last parameter of the method and to specify the type of this parameter as a pointer to an error object pointer (also known as double-indirection).
The following example declares a method named getGreeting that has an error object of type NSError as
its parameter.
This approach enables the called method to modify the pointer the error object points to, and if an error occurs, return an error object specific to the method call.
A return value for the method is required. It is either an object pointer or a Boolean
value. Your code invokes such a method by including a reference to an error object as its last parameter, or providingNULL as
the last parameter if you don’t need to access the error. After the method is invoked, the result is inspected. If the value is NO or nil,
then the error object should be processed; else no error object was returned. Many Foundation classes have methods that return an error object by indirection. In addition, your classes can use this convention to implement methods that return an error object.
Listing
14-2 depicts a class named FileWriter, which declares a method that (indirectly) returns an error object.
Listing
14-2. FileWriter Interface with Method That Returns an NSError Object
For your code to call this method on a FileWriter object, it must first declare an NSError object,
as shown in Listing
14-3, and then check the return value to see if an error occurred.
Listing
14-3. Invoking FileWriter Method That Returns an NSError Object
Now you’ll create a couple of example programs that perform error handling for error objects passed by delegation methods and error objects obtained via indirection.
Handling Delegation Method Errors
Now you’ll implement a program that performs error handling for
a delegate method. In Chapter 11,
you implemented a program, NetConnector, which demonstrates URL loading using the Foundation Framework NSURLConnection class.
Here you’ll update this program to handle errors when loading a URL.
In Xcode, open the NetConnector project by selecting Open
NetConnector.xcodeproj from
the Xcode File menu. The source code for the project consists of three files that implement theNetConnector class
and the main function. Let’s start by making some updates to the NetConnectorclass. Select the NetConnector.m file
in the navigator pane, and then update the NetConnector implementation (updates in bold), as shown in Listing
14-4.
Listing
14-4. NetConnector Class Implementation, Updated to Handle Errors
An NSURLConnection sends
the connection:didFailWithError: message
to its delegate object if the connection doesn’t load its request successfully. As shown in Listing
14-4, the NetConnector class is set as the delegate for
its NSURLConnection object, and hence its connection:didFailWithError: method will be invoked on request load
errors. The method implementation retrieves the properties of the NSError object: description, domain, code, and user
info. The URL of the failed load request is stored in the user info dictionary. Its key is NSURLErrorFailingURLErrorKey,
one of the NSError standard user info dictionary keys listed in Table
14-1. The method logs the values of this data to the output pane.
Next, you will update the main() function, but before you do that, you need to create
a page with a valid URL that cannot be loaded. Doing this forces an error to occur when you attempt to load the page using an NSURLConnection object.
Open an OS X terminal window and enter the Unix commands shown in Listing
14-5.
Listing
14-5. Using the Mac OS X Terminal Utility to Create a File
The touch command creates
a new, empty file. As shown in Listing
14-6, the full path for the file is/tmp/ProtectedPage.html. The chmod u-r command
removes read access to the file for the current user. The corresponding URL for this resource is file:///tmp/ProtectedPage.html.
OK, now that this resource is configured properly, let’s update the main() function. Select the main.m file
in the navigator pane, and then update the main() function, as shown in Listing
14-6.
Listing
14-6. NetConnector main( ) Function Implementation
The key change in the main() function is the URL. It is updated to the URL for the resource
that you created earlier, file:///tmp/ProtectedPage.html. The code will attempt to asynchronously load
this resource (with an NSURLConnection object) using the NetConnector initWithRequest: method.
As shown in Listing 14-4, the NetConnector class
implements the connection:didFailWithError:method to handle errors loading a URL.
Now save, compile, and run the updated NetConnector program and observe the messages in the output pane (as shown in Figure
14-1).
Figure
14-1. Testing the NSError portion of the updated NetConnector project
The messages in the output pane show that the NSURLConnection failed
to load the URL, and hence sent the connection:didFailWithError: message to its delegate object—in this case,
theNetConnector instance. As shown in the method implementation of Listing
14-4, the error description, failed URL, error code, and domain are logged to the output pane. OK, great. Now that you’ve got that under your belt, let’s implement a program that returns an error
object via indirection.
Creating Errors Objects via Indirection
Now you will create a program that demonstrates error handling for a Foundation Framework object. In Xcode, create a new project by selecting New Project . . . from
the Xcode File menu. In the New Project Assistant pane, create a command-line application. In the Project Options window, specifyFMErrorObject for the Product Name, choose Foundation for
the Project Type, and select ARC memory management by selecting the Use Automatic Reference Counting check box. Specify the location in your file system where you want the project to be
created (if necessary select New Folderand enter the name and location for the folder), uncheck the Source Control check box, and then click the Create button.
In the Xcode project navigator, select the main.m file and update the main() function, as shown inListing
14-7.
Listing
14-7. FMErrorObject main( ) Function Implementation
Logically, the code uses an NSFileManager instance method to remove a file from the
file system. If an error occurs when invoking the method, it returns an error object via indirection that describes the error, along with an appropriate return result. As shown in Listing
14-7, the file begins by defining a variable, FILE_PATH,
which represents the full path of a file on the local file system (in order to test error object creation and processing make sure that this file, /tmp/NoSuchFile.txt,
doesn’t exist). The main() function begins by creating a FileManager object
and an NSError pointer. It then attempts to delete the file by invoking the NSFileManager removeItemAtPath:error: method.
As the error parameter is not NULL, an NSError object
will be returned if an error occurs when invoking this method.
Next, a conditional expression is performed using the Boolean result of this method; if the returned value is NO,
then an error occurred trying to remove the file and the body of the conditional expression is executed. This code retrieves the properties of the NSError object:
description, domain, code, and user info. The full path of the file that couldn’t be removed is stored in the user info dictionary. Its key is NSFilePathErrorKey,
one of the NSError standard user info dictionary keys listed in Table
14-1. The method logs the values of this data to the output pane.
Now save, compile, and run the FMErrorObject program and observe the messages in
the output pane (as shown in Figure
14-2).
Figure
14-2. Testing NSError by indirection in the FMErrorObject project
The messages in the output pane show that the NSFileManager object failed to remove the
file, and hence set an error object (via indirection) in the error parameter of the removeFileWithPath:error:method,
and set its return result to NO. The error description, file path, error code, and domain are logged to the output
pane. Perfect. Now that you understand how to retrieve and process error objects, let’s examine the Foundation Framework support for error recovery.
Error Recovery
The NSError class provides a mechanism for recovering from errors. TheNSErrorRecoveryAttempting informal
protocol provides methods that are implemented to perform error recovery.
An object that adopts this protocol must implement at least one of its two methods for attempting recovery from errors. The user info dictionary of an NSError object
that supports error recovery must contain, at a minimum, the following three entries:
The recovery attempter object (retrieved using the keyNSRecoveryAttempterErrorKey)
The recovery options (retrieved using the keyNSLocalizedRecoveryOptionsErrorKey)
A localized recovery suggestion string (retrieved using the keyNSLocalizedRecoverySuggestionErrorKey)
The recovery attempter may implement any logic appropriate for error recovery. Note that the error recovery functionality is only available on the Apple OS X platform.
Error Responders
The Application Kit provides APIs and mechanisms that can be used to respond to
errors encapsulated in NSError objects. The NSResponder class
defines an error responder chain used to pass events and action messages up the view hierarchy. It includes methods to display information in the associatedNSError object,
and then forwards the error message to the next responder. This enables each object in the hierarchy to handle the error appropriately, perhaps by adding additional information pertaining to the error. Note that the error responder functionality is available
only on the Apple OS X platform.
NSError Codes
The Foundation Framework defines a number of standard NSError codes as
Foundation constants. These errors are enumerations defined for the following NSError class error domains, as follows:
Cocoa (NSErrorCocoaDomain)
URL Loading System (NSURLDomain)
The Foundation Framework NSError class is
used to create error objects. The properties of this class are an error code, the error domain, and a dictionary of user information. The class includes methods
for creating and initializing error objects, retrieving error properties, getting a localized error description, and facilitating error recovery.
An error domain is a mechanism used to organize error codes according to a system, subsystem, framework,
and so forth. Error domains enable you to identify the subsystem, framework, and so forth, that detected the error. They also help prevent naming collisions between error codes, because error codes between different domains can have the same value.
The user info dictionary is anNSDictionary instance that holds error information beyond the code
and domain. The types of information that can be stored in this dictionary include localized error information and references to supporting objects. The following statement creates an error object using the NSError class
factory method errorWithDomain:code:userInfo:.
NSError *err = [NSError errorWithDomain:NSCocoaErrorDomain code:NSFileNoSuchFileError userInfo:nil];
This particular error would be created if, for example, a file is not found at the path specified. Notice that the user info dictionary is not provided (the userInfo parameter
is set to nil). Listing
14-1creates the same error object, this time with a user info dictionary.
Listing
14-1. Creating an NSError Object
NSString *desc = NSLocalizedString(@"FileNotFound", @""); NSDictionary *info = @{NSLocalizedDescriptionKey:desc}; NSError *err = [NSError errorWithDomain:NSCocoaErrorDomain code:NSFileNoSuchFileError userInfo:info];
Listing 14-1 shows
the user info dictionary for this example consists of one entry, the key-value pair for a localized description. The localized string is created using the Foundation NSLocalizedStringfunction.
The constant NSLocalizedDescriptionKey is
a standard user info dictionary key defined in the NSError class.
The Foundation Framework declares four major error domains:
NSMachErrorDomain: OS kernel error codes.
NSPOSIXErrorDomain: Error codes derived from standard POSIX-conforming versions of Unix,
such as BSD.
NSOSStatusErrorDomain: Error codes specific to Apple OS X Core Services and the Carbon framework.
NSCocoaErrorDomain: All of the error codes for the Cocoa frameworks (this includes the Foundation
Framework and other Objective-C frameworks).
In addition to the major error domains presented here, there are also error domains for frameworks, groups of classes, and even individual classes. The NSError class
also enables you to create your own error domain when creating and initializing an NSError object. As mentioned previously, Listing
14-1uses the constant NSLocalizedDescriptionKey. The NSError class
defines a set of common user info dictionary keys that can be used to create the key-value pairs
for the user info dictionary. These keys are listed in Table
14-1.
Table
14-1. NSError Standard User Info Dictionary Keys
Key | Value Description |
---|---|
NSLocalizedDescriptionKey | Localized string representation of the error. |
NSFilePathErrorKey | The file path of the error. |
NSStringEncodingErrorKey | An NSNumber object containing the string encoding value. |
NSUnderlyingErrorKey | The error encountered in an underlying implementation (which caused this error). |
NSURLErroKey | An NSURL object. |
NSLocalizedFailureReasonErroryKey | Localized string representation of the reason that caused the error. |
NSLocalizedRecoverySuggestionErrorKey | Localized recovery suggestion for the error. |
NSLocalizedRecoveryOptionsErrorKey | NSArray containing the localized titles of buttons for display in an alert panel. |
NSRecoveryAttempterErrorKey | An object that conforms to theNSErrorRecoveryAttempting protocol. |
NSHelpAnchorErrorKey | Localized string representation of help information for a help button. |
NSURLErrorFailingURLString | NSURL object containing the URL that caused the load to fail. |
NSURLErrorFailingURLStringErrorKey | String for the URL that caused the load to fail. |
NSURLErrorFailingURLPeerTrustErrorKey | SecTrustRef object representing the state of a failed SSL handshake. |
OK, so now you know how to create NSError objects, but how do you use them? In
general, there are two scenarios for obtaining NSError objects:
Delegation: An error object passed as a parameter to a delegation method that you implement.
Indirection: An error object retrieved via indirection from a method that your code invokes.
The delegation pattern is a design pattern whereby an object (the delegator) delegates one or more
tasks to another delegate object. The tasks are encapsulated in the method(s) of the delegate object. When necessary, the delegator invokes the appropriate method on the delegate object, providing any required parameters. Many Foundation Framework
classes implement the delegation pattern to enable custom error handling. The delegating Foundation object invokes a method on a delegate object (custom code that you implement) that includes an error object as a parameter.
The NSURLConnectionDelegate protocol declares a delegation method (connection:didFailWithError:)
that returns an error object:
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error;
This protocol is used for asynchronously loading a URL request via an NSURLConnection object.
Your code implements a delegate object that conforms to this protocol and sets it as the delegate of theNSURLConnection object.
Your code then loads the URL request asynchronously, and if an error occurs, the delegating (NSURLConnection)
object invokes the connection:didFailWithError:method
on your delegate object.
A common Objective-C programming convention for methods that return an error object is
to make this the last parameter of the method and to specify the type of this parameter as a pointer to an error object pointer (also known as double-indirection).
The following example declares a method named getGreeting that has an error object of type NSError as
its parameter.
- (NSString *)getGreeting(NSError **error);
This approach enables the called method to modify the pointer the error object points to, and if an error occurs, return an error object specific to the method call.
A return value for the method is required. It is either an object pointer or a Boolean
value. Your code invokes such a method by including a reference to an error object as its last parameter, or providingNULL as
the last parameter if you don’t need to access the error. After the method is invoked, the result is inspected. If the value is NO or nil,
then the error object should be processed; else no error object was returned. Many Foundation classes have methods that return an error object by indirection. In addition, your classes can use this convention to implement methods that return an error object.
Listing
14-2 depicts a class named FileWriter, which declares a method that (indirectly) returns an error object.
Listing
14-2. FileWriter Interface with Method That Returns an NSError Object
@interface FileWriter : NSObject + (BOOL) writeData:(NSData *)data toFile:(NSString *)path error:(NSError **)err; @end
For your code to call this method on a FileWriter object, it must first declare an NSError object,
as shown in Listing
14-3, and then check the return value to see if an error occurred.
Listing
14-3. Invoking FileWriter Method That Returns an NSError Object
NSError *writeErr; NSData *greeting = [@"Hello, World" dataUsingEncoding:NSUTF8StringEncoding]; BOOL success = [FileWriter writeData:greeting toFile:NSTemporaryDirectory() error:&writeErr]; if (!success) { // Process error ... }
Now you’ll create a couple of example programs that perform error handling for error objects passed by delegation methods and error objects obtained via indirection.
Handling Delegation Method Errors
Now you’ll implement a program that performs error handling for
a delegate method. In Chapter 11,
you implemented a program, NetConnector, which demonstrates URL loading using the Foundation Framework NSURLConnection class.
Here you’ll update this program to handle errors when loading a URL.
In Xcode, open the NetConnector project by selecting Open
NetConnector.xcodeproj from
the Xcode File menu. The source code for the project consists of three files that implement theNetConnector class
and the main function. Let’s start by making some updates to the NetConnectorclass. Select the NetConnector.m file
in the navigator pane, and then update the NetConnector implementation (updates in bold), as shown in Listing
14-4.
Listing
14-4. NetConnector Class Implementation, Updated to Handle Errors
#import "NetConnector.h" @interface NetConnector() @property NSURLRequest *request; @property BOOL isFinished; @property NSURLConnection *connector; @property NSMutableData *receivedData; @end @implementation NetConnector - (id) initWithRequest:(NSURLRequest *)request { if ((self = [super init])) { _request = request; _finishedLoading = NO; // Create URL cache with appropriate in-memory storage NSURLCache *URLCache = [[NSURLCache alloc] init]; [URLCache setMemoryCapacity:CACHE_MEMORY_SIZE]; [NSURLCache setSharedURLCache:URLCache]; // Create connection and begin downloading data from resource _connector = [NSURLConnection connectionWithRequest:request delegate:self]; } return self; } - (void) reloadRequest { self.finishedLoading = NO; self.connector = [NSURLConnection connectionWithRequest:self.request delegate:self]; } #pragma mark - #pragma mark Delegate methods - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { NSString *description = [error localizedDescription]; NSString *domain = [error domain]; NSInteger code = [error code]; NSDictionary *info = [error userInfo]; NSURL *failedUrl = (NSURL *)[info objectForKey:NSURLErrorFailingURLErrorKey]; NSLog(@"\n*** ERROR ***\nDescription-> %@\nURL-> %@\nDomain-> %@\nCode-> %li", description, failedUrl, domain, code); self.finishedLoading = YES; } - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { if (self.receivedData != nil) { [self.receivedData setLength:0]; } } - (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse { NSURLResponse *response = [cachedResponse response]; NSURL *url = [response URL]; if ([[url scheme] isEqualTo:HTTP_SCHEME]) { NSLog(@"Downloaded data, caching response"); return cachedResponse; } else { NSLog(@"Downloaded data, not caching response"); return nil; } } - (void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)data { if (self.receivedData != nil) { [self.receivedData appendData:data]; } else { self.receivedData = [[NSMutableData alloc] initWithData:data]; } } - (void)connectionDidFinishLoading:(NSURLConnection *)connection { NSUInteger length = [self.receivedData length]; NSLog(@"Downloaded %lu bytes from request %@", length, self.request); // Loaded data, set flag to exit run loop self.finishedLoading = YES; } @end
An NSURLConnection sends
the connection:didFailWithError: message
to its delegate object if the connection doesn’t load its request successfully. As shown in Listing
14-4, the NetConnector class is set as the delegate for
its NSURLConnection object, and hence its connection:didFailWithError: method will be invoked on request load
errors. The method implementation retrieves the properties of the NSError object: description, domain, code, and user
info. The URL of the failed load request is stored in the user info dictionary. Its key is NSURLErrorFailingURLErrorKey,
one of the NSError standard user info dictionary keys listed in Table
14-1. The method logs the values of this data to the output pane.
Next, you will update the main() function, but before you do that, you need to create
a page with a valid URL that cannot be loaded. Doing this forces an error to occur when you attempt to load the page using an NSURLConnection object.
Open an OS X terminal window and enter the Unix commands shown in Listing
14-5.
Listing
14-5. Using the Mac OS X Terminal Utility to Create a File
touch /tmp/ProtectedPage.html chmod u-r /tmp/ProtectedPage.html
The touch command creates
a new, empty file. As shown in Listing
14-6, the full path for the file is/tmp/ProtectedPage.html. The chmod u-r command
removes read access to the file for the current user. The corresponding URL for this resource is file:///tmp/ProtectedPage.html.
OK, now that this resource is configured properly, let’s update the main() function. Select the main.m file
in the navigator pane, and then update the main() function, as shown in Listing
14-6.
Listing
14-6. NetConnector main( ) Function Implementation
#import <Foundation/Foundation.h> #import "NetConnector.h" #define INDEX_URL @"file:///tmp/ProtectedPage.html" int main(int argc, const char * argv[]) { @autoreleasepool { // Retrieve the current run loop for the connection NSRunLoop *loop = [NSRunLoop currentRunLoop]; // Create the request with specified cache policy, then begin downloading! NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:INDEX_URL] cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:5]; NetConnector *netConnect = [[NetConnector alloc] initWithRequest:request]; // Loop until finished loading the resource while (!netConnect.finishedLoading && [loop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]); // Zero out cache [[NSURLCache sharedURLCache] removeAllCachedResponses]; } return 0; }
The key change in the main() function is the URL. It is updated to the URL for the resource
that you created earlier, file:///tmp/ProtectedPage.html. The code will attempt to asynchronously load
this resource (with an NSURLConnection object) using the NetConnector initWithRequest: method.
As shown in Listing 14-4, the NetConnector class
implements the connection:didFailWithError:method to handle errors loading a URL.
Now save, compile, and run the updated NetConnector program and observe the messages in the output pane (as shown in Figure
14-1).
Figure
14-1. Testing the NSError portion of the updated NetConnector project
The messages in the output pane show that the NSURLConnection failed
to load the URL, and hence sent the connection:didFailWithError: message to its delegate object—in this case,
theNetConnector instance. As shown in the method implementation of Listing
14-4, the error description, failed URL, error code, and domain are logged to the output pane. OK, great. Now that you’ve got that under your belt, let’s implement a program that returns an error
object via indirection.
Creating Errors Objects via Indirection
Now you will create a program that demonstrates error handling for a Foundation Framework object. In Xcode, create a new project by selecting New Project . . . from
the Xcode File menu. In the New Project Assistant pane, create a command-line application. In the Project Options window, specifyFMErrorObject for the Product Name, choose Foundation for
the Project Type, and select ARC memory management by selecting the Use Automatic Reference Counting check box. Specify the location in your file system where you want the project to be
created (if necessary select New Folderand enter the name and location for the folder), uncheck the Source Control check box, and then click the Create button.
In the Xcode project navigator, select the main.m file and update the main() function, as shown inListing
14-7.
Listing
14-7. FMErrorObject main( ) Function Implementation
#import <Foundation/Foundation.h> #define FILE_PATH @"/tmp/NoSuchFile.txt" int main(int argc, const char * argv[]) { @autoreleasepool { NSFileManager *fileMgr = [NSFileManager defaultManager]; NSError *fileErr; BOOL success = [fileMgr removeItemAtPath:FILE_PATH error:&fileErr]; if (!success) { NSString *description = [fileErr localizedDescription]; NSString *domain = [fileErr domain]; NSInteger code = [fileErr code]; NSDictionary *info = [fileErr userInfo]; NSURL *failedPath = (NSURL *)[info objectForKey:NSFilePathErrorKey]; NSLog(@"\n*** ERROR ***\nDescription-> %@\nPath-> %@\nDomain-> %@\nCode-> %li", description, failedPath, domain, code); } } return 0; }
Logically, the code uses an NSFileManager instance method to remove a file from the
file system. If an error occurs when invoking the method, it returns an error object via indirection that describes the error, along with an appropriate return result. As shown in Listing
14-7, the file begins by defining a variable, FILE_PATH,
which represents the full path of a file on the local file system (in order to test error object creation and processing make sure that this file, /tmp/NoSuchFile.txt,
doesn’t exist). The main() function begins by creating a FileManager object
and an NSError pointer. It then attempts to delete the file by invoking the NSFileManager removeItemAtPath:error: method.
As the error parameter is not NULL, an NSError object
will be returned if an error occurs when invoking this method.
Next, a conditional expression is performed using the Boolean result of this method; if the returned value is NO,
then an error occurred trying to remove the file and the body of the conditional expression is executed. This code retrieves the properties of the NSError object:
description, domain, code, and user info. The full path of the file that couldn’t be removed is stored in the user info dictionary. Its key is NSFilePathErrorKey,
one of the NSError standard user info dictionary keys listed in Table
14-1. The method logs the values of this data to the output pane.
Now save, compile, and run the FMErrorObject program and observe the messages in
the output pane (as shown in Figure
14-2).
Figure
14-2. Testing NSError by indirection in the FMErrorObject project
The messages in the output pane show that the NSFileManager object failed to remove the
file, and hence set an error object (via indirection) in the error parameter of the removeFileWithPath:error:method,
and set its return result to NO. The error description, file path, error code, and domain are logged to the output
pane. Perfect. Now that you understand how to retrieve and process error objects, let’s examine the Foundation Framework support for error recovery.
Error Recovery
The NSError class provides a mechanism for recovering from errors. TheNSErrorRecoveryAttempting informal
protocol provides methods that are implemented to perform error recovery.
An object that adopts this protocol must implement at least one of its two methods for attempting recovery from errors. The user info dictionary of an NSError object
that supports error recovery must contain, at a minimum, the following three entries:
The recovery attempter object (retrieved using the keyNSRecoveryAttempterErrorKey)
The recovery options (retrieved using the keyNSLocalizedRecoveryOptionsErrorKey)
A localized recovery suggestion string (retrieved using the keyNSLocalizedRecoverySuggestionErrorKey)
The recovery attempter may implement any logic appropriate for error recovery. Note that the error recovery functionality is only available on the Apple OS X platform.
Error Responders
The Application Kit provides APIs and mechanisms that can be used to respond to
errors encapsulated in NSError objects. The NSResponder class
defines an error responder chain used to pass events and action messages up the view hierarchy. It includes methods to display information in the associatedNSError object,
and then forwards the error message to the next responder. This enables each object in the hierarchy to handle the error appropriately, perhaps by adding additional information pertaining to the error. Note that the error responder functionality is available
only on the Apple OS X platform.
NSError Codes
The Foundation Framework defines a number of standard NSError codes as
Foundation constants. These errors are enumerations defined for the following NSError class error domains, as follows:
Cocoa (NSErrorCocoaDomain)
URL Loading System (NSURLDomain)
相关文章推荐
- Brief Intro to Concurrency and Threading of Foundation Framework
- Brief Intro to Container Literals of Foundation Framework
- Brief Intro to URL Handling of Foundation Framework (Examples: Downloading from a URL)
- Brief Intro to Value Objects of Foundation Framework
- Brief Intro to Archives and Serialization of Foundation Framework
- Brief Intro to Strings of Foundation Framework
- Brief Intro to Interprocess Communication of Foundation Framework
- Brief Intro to Exception Handling of Foundation Framework
- Brief Intro to Network Services of Foundation Framework
- Brief Intro to NSException of Foundation Framework
- Brief Intro to File System Utilities of Foundation Framework
- Brief Intro to Object Subscripting of Foundation Framework
- Brief Intro to Notifications of Foundation Framework
- Brief Intro to Error handling of Foundation Framework
- Brief Intro to Operations and Operation Queues of Foundation Framework
- Brief Intro to NSNumber Literals of Foundation Frameworks
- Brief Intro to Collections of Foundation Frameworks
- Brief Intro to Foundation Functions
- : Exception sending context initialized event to listener instance of class org.springframework.web.
- .Net Framework Initialization Error – Unable to find a version of the runtime to run this applicatio