在objective-c/cocoa中抛出异常的最佳方法是什么?
当前回答
@throw([NSException exceptionWith…])
Xcode将@throw语句识别为函数出口点,就像return语句一样。使用@throw语法可以避免错误的“Control may reach end of non-void function”警告,你可能会从[NSException raise:…]得到这种警告。
同样,@throw也可以用来抛出不属于NSException类的对象。
其他回答
@throw([NSException exceptionWithName:…
- (void)parseError:(NSError *)error
completionBlock:(void (^)(NSString *error))completionBlock {
NSString *resultString = [NSString new];
@try {
NSData *errorData = [NSData dataWithData:error.userInfo[@"SomeKeyForData"]];
if(!errorData.bytes) {
@throw([NSException exceptionWithName:@"<Set Yours exc. name: > Test Exc" reason:@"<Describe reason: > Doesn't contain data" userInfo:nil]);
}
NSDictionary *dictFromData = [NSJSONSerialization JSONObjectWithData:errorData
options:NSJSONReadingAllowFragments
error:&error];
resultString = dictFromData[@"someKey"];
...
} @catch (NSException *exception) {
NSLog( @"Caught Exception Name: %@", exception.name);
NSLog( @"Caught Exception Reason: %@", exception.reason );
resultString = exception.reason;
} @finally {
completionBlock(resultString);
}
}
使用:
[self parseError:error completionBlock:^(NSString *error) {
NSLog(@"%@", error);
}];
另一个更高级的用例:
- (void)parseError:(NSError *)error completionBlock:(void (^)(NSString *error))completionBlock {
NSString *resultString = [NSString new];
NSException* customNilException = [NSException exceptionWithName:@"NilException"
reason:@"object is nil"
userInfo:nil];
NSException* customNotNumberException = [NSException exceptionWithName:@"NotNumberException"
reason:@"object is not a NSNumber"
userInfo:nil];
@try {
NSData *errorData = [NSData dataWithData:error.userInfo[@"SomeKeyForData"]];
if(!errorData.bytes) {
@throw([NSException exceptionWithName:@"<Set Yours exc. name: > Test Exc" reason:@"<Describe reason: > Doesn't contain data" userInfo:nil]);
}
NSDictionary *dictFromData = [NSJSONSerialization JSONObjectWithData:errorData
options:NSJSONReadingAllowFragments
error:&error];
NSArray * array = dictFromData[@"someArrayKey"];
for (NSInteger i=0; i < array.count; i++) {
id resultString = array[i];
if (![resultString isKindOfClass:NSNumber.class]) {
[customNotNumberException raise]; // <====== HERE is just the same as: @throw customNotNumberException;
break;
} else if (!resultString){
@throw customNilException; // <======
break;
}
}
} @catch (SomeCustomException * sce) {
// most specific type
// handle exception ce
//...
} @catch (CustomException * ce) {
// most specific type
// handle exception ce
//...
} @catch (NSException *exception) {
// less specific type
// do whatever recovery is necessary at his level
//...
// rethrow the exception so it's handled at a higher level
@throw (SomeCustomException * customException);
} @finally {
// perform tasks necessary whether exception occurred or not
}
}
这是我从“大书呆子牧场指南(第四版)”中学到的:
@throw [NSException exceptionWithName:@"Something is not right exception"
reason:@"Can't perform this operation because of this or that"
userInfo:nil];
这里有一个警告。在Objective-C中,与许多类似的语言不同,您通常应该尽量避免在正常操作中可能发生的常见错误情况下使用异常。
Apple的Obj-C 2.0文档中写道:“重要的是:异常在Objective-C中是资源密集型的。您不应将异常用于一般的流控制,或仅用于表示错误(例如文件不可访问)”
Apple's conceptual Exception handling documentation explains the same, but with more words: "Important: You should reserve the use of exceptions for programming or unexpected runtime errors such as out-of-bounds collection access, attempts to mutate immutable objects, sending an invalid message, and losing the connection to the window server. You usually take care of these sorts of errors with exceptions when an application is being created rather than at runtime. [.....] Instead of exceptions, error objects (NSError) and the Cocoa error-delivery mechanism are the recommended way to communicate expected errors in Cocoa applications."
这样做的部分原因是坚持Objective-C中的编程习惯(在简单的情况下使用返回值,在更复杂的情况下使用按引用参数(通常是NSError类)),部分原因是抛出和捕获异常的代价要高得多,最后(可能是最重要的)Objective-C异常是C的setjmp()和longjmp()函数的一个瘦包装,本质上混乱了你仔细的内存处理,参见下面的解释。
我认为你永远不应该使用异常来控制正常的程序流程。但是,当某些值与所需值不匹配时,应该抛出异常。
例如,如果某个函数接受一个值,并且该值永远不允许为nil,那么就可以抛出一个异常,而不是尝试做一些“聪明”的事情……
Ries
@throw([NSException exceptionWith…])
Xcode将@throw语句识别为函数出口点,就像return语句一样。使用@throw语法可以避免错误的“Control may reach end of non-void function”警告,你可能会从[NSException raise:…]得到这种警告。
同样,@throw也可以用来抛出不属于NSException类的对象。
推荐文章
- 如何停止不必要的UIButton动画标题变化?
- 如何在我的iPhone应用程序中使用NSError ?
- Objective-C中的自动引用计数不能防止或减少什么样的泄漏?
- 如何精确地以毫秒为单位记录方法的执行时间?
- 保存字符串到NSUserDefaults?
- 查看保存的NSUserDefaults的简单方法?
- 如何添加UITableViewCell之间的间距
- 在为设备编译时,Apple Mach-O连接器错误
- 理解设置
- 架构i386的未定义符号:_OBJC_CLASS_$_SKPSMTPMessage",引用自:错误
- Objective-C中方法混合的危险是什么?
- 如何使用接口生成器创建的nib文件加载UIView
- 如何设置回退按钮文本在Swift
- 如何比较两个nsdate:哪个是最近的?
- 使UINavigationBar透明