creating a recoverable NSError with ease
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
typedef void (^CFAErrorRecoveryHandler)(NSUInteger optionIndex); | |
@interface CFANSErrorRecoveyrAttempter : NSObject //<NSErrorRecoveryAttempting> | |
{ | |
CFAErrorRecoveryHandler _handler; | |
} | |
- (id)initWithHandler:(CFAErrorRecoveryHandler)block; | |
+ (CFANSErrorRecoveyrAttempter *)attempterWithHandler:(CFAErrorRecoveryHandler)block; | |
@end | |
@implementation CFANSErrorRecoveyrAttempter | |
- (id)initWithHandler:(CFAErrorRecoveryHandler)block | |
{ | |
self = [super init]; | |
if (self) { | |
_handler = Block_copy(block); | |
} | |
return self; | |
} | |
- (void)dealloc | |
{ | |
if (_handler) { Block_release(_handler), _handler = nil; } | |
[super dealloc]; | |
} | |
+ (CFANSErrorRecoveyrAttempter *)attempterWithHandler:(CFAErrorRecoveryHandler)block | |
{ | |
CFANSErrorRecoveyrAttempter *attempter = [[CFANSErrorRecoveyrAttempter alloc] initWithHandler:block]; | |
return [attempter autorelease]; | |
} | |
#pragma mark NSErrorRecoveryAttempting Protocol | |
// This will be invoked while the error was presented with -[NSView presentError:modalForWindow:....] | |
- (void)attemptRecoveryFromError:(NSError *)error optionIndex:(NSUInteger)recoveryOptionIndex delegate:(id)delegate didRecoverSelector:(SEL)didRecoverSelector contextInfo:(void *)contextInfo | |
{ | |
if (_handler) _handler(recoveryOptionIndex); | |
} | |
// This will be invoked while the error was presented with -[NSApp presentError:] | |
- (BOOL)attemptRecoveryFromError:(NSError *)error optionIndex:(NSUInteger)recoveryOptionIndex | |
{ | |
if (_handler) _handler(recoveryOptionIndex); | |
return YES; | |
} | |
@end | |
@interface NSError (RecoverableNSError) | |
#pragma mark Recoverable Error | |
/// --------------------------------- | |
/// @name NSError Creation | |
/// --------------------------------- | |
/// Create a recoverable NSError | |
/// The NSError instance can be presented as a floating panel using -[NSApp presentError:] or as a sheet using -[NSView presentError:...] | |
/// @param title | |
/// Briefly describe the error; which is the value for NSLocalizedDescriptionKey | |
/// @param suggestion | |
/// Suggest users what to do. The suggestion should be relevant to the recovery options; | |
/// which is the value for NSLocalizedRecoverySuggestionErrorKey | |
/// @param options | |
/// NSArray of NSStrings; which is the value for NSLocalizedRecoveryOptionsErrorKey | |
/// Basically there should be fewer than 3(or equal to) options and the options obey the exact index sequence as | |
/// follow. index 0: default option, index 1: alternate option, index 2: other option | |
/// @param handler | |
/// recover your error based on the selected option. | |
/// Please remember that the handler block will not be triggered before | |
/// the error was presented to the users. (eg: [NSApp presentError:error];) | |
+ (NSError *)cfa_errorWithTitle:(NSString *)title | |
recoverySuggestion:(NSString *)suggestion | |
recoveryOptions:(NSArray *)options | |
recoveryHandler:(CFAErrorRecoveryHandler)handler; | |
@end | |
@implementation NSError (RecoverableNSError) | |
+ (NSError *)cfa_errorWithTitle:(NSString *)title | |
recoverySuggestion:(NSString *)suggestion | |
recoveryOptions:(NSArray *)options | |
recoveryHandler:(CFAErrorRecoveryHandler)handler | |
{ | |
NSMutableDictionary *info = [[NSMutableDictionary alloc] initWithCapacity:0]; | |
[info setObject:title forKey:NSLocalizedDescriptionKey]; | |
[info setObject:suggestion forKey:NSLocalizedRecoverySuggestionErrorKey]; | |
[info setObject:options forKey:NSLocalizedRecoveryOptionsErrorKey]; | |
[info setObject:[CFANSErrorRecoveyrAttempter attempterWithHandler:handler] forKey:NSRecoveryAttempterErrorKey]; | |
NSError *error = [NSError errorWithDomain:@"com.cocoafaculty.ErrorDomain" code:0 userInfo:info]; | |
[info release]; | |
return error; | |
} | |
@end |
Thank you, Mike. Very informative resources. 👍
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
See also: