在开发过程中,总是会遇到各种Exception,在此总结一些常见的Exception。
NSInvalidArgumentException
错误类型 | NSInvalidArgumentException |
---|---|
log输出 | unrecognized selector sent to instance xxxx |
错误释义 | 给实体对象发送了不认识的消息,即对象调用方法出错 |
错误基本原因 | Objective-C的方法调用其实是基于消息传递机制,并且是动态编译。因此在编译阶段不会进行类和方法的绑定,而是在运行时执行绑定操作。当类的方法没有实现或对象被提前release时,这个问题会在运行时表现出来,从而导致App崩溃 |
常见场景
场景1 给对象发送消息时:
[self performSelector:@selector(testException:) withObject:@"string"];
-(void)testException {
NSLog(@"%s",__func__);
}
错误分析:给对象发消息的时候,该消息是带形参的,而实现的方法却不带形参,因此产生了异常。
场景2 在集合中:
NSMutableArray *array = [NSMutableArray array];
[array addObject:nil];
错误分析:当企图给集合插入nil值的时候,实际上调用的是[__NSArrayM insertObject: atIndex: ],根据CFArray的源码推断,在该方法里面,对插入的对象进行了断言操作(仅仅是猜想,未能找到CFMutableArray的源码)。
场景3 在代理中:
@protocol requestDelegate <NSObject>
-(void)sendRequest:(NSURL *)url;
@end
@implementation DelegateManager
-(BOOL)doRequest:(NSURL *)url {
...
if (delegate) {
...
return [delegate sendRequest:url];
}
...
return NO;
}
@end
delegate作为设计模式的一种,贯穿于App中。通常我们会将delegate定义为id类型,也就意味着,任何对象都有可能成为代理。成为代理的实例可能只是遵守了协议,但是却没对协议的方法进行具体实现。在上面的场景中,有可能代理对象并没有实现sendRequest:方法,此时调用sendRequest:方法就会出现崩溃。
正确的操作
在给delegate发送消息之前应该进行respondsToSelector判断
-(BOOL)doRequest:(NSURL *)url {
...
if (delegate && [delegate respondsToSelector:@selector(sendRequest:)]) {
...
return [delegate sendRequest:url];
}
...
return NO;
}
NSRangeException
错误类型 | NSRangeException |
---|---|
log输出 | 1.index 2 beyond bounds [0 .. 1] 2.index x beyond bounds for .. |
错误释义 | 1.索引序号2超出0~1区间 2.索引序号超出... |
常见场景
场景1 插入或获取对象:
NSMutableArray *array = [NSMutableArray array];
[array addObject:@"one"];
[array addObject:@"two"];
[array objectAtIndex:2];
错误分析:当试图从数组中获得一个对象的时候,索引大于自身容量,因而引起该异常。同样在插入的时候,不正确的索引值也会引发这个问题。
场景2 截取字符串:
NSMutableString *str = [[NSMutableString alloc] initWithString:@"one"];
[str substringFromIndex:5];
错误分析:当试图截取字符串的时候,起始索引大于字符串本身长度。
NSGenericException
错误类型 | NSGenericException |
---|---|
log输出 | xxxxxx was mutated while being enumerated. |
错误释义 | 对象xxxxxx在枚举的时候是不可变的 |
常见场景
场景1 遍历的时候添加或移除对象:
NSMutableArray *array = [NSMutableArray arrayWithObjects:@"1",@"2",@"3",nil];
for (NSString *string in array) {
[array addObject:@"4"];
// [array removeObject:@"66"];
}
错误分析:在遍历的时候,对集合进行了插入/删除操作。
NSFileHandleOperationException
错误类型 | NSFileHandleOperationException |
---|---|
log输出 | Bad file descriptor |
错误释义 | 错误的文件描述符 |
常见场景
场景1 对文件进行操作:
NSString *path = NSHomeDirectory();
NSString *filePath = [path stringByAppendingPathComponent:@"1.txt"];
NSFileHandle *fileHandle = [NSFileHandle fileHandleForReadingAtPath:filePath];
[fileHandle seekToEndOfFile];
NSData *data = [@"Hello World" dataUsingEncoding:NSUTF8StringEncoding];
[fileHandle writeData:data];
[fileHandle closeFile];
错误分析:企图对文件进行写操作,但获取句柄时,请求的确是只读句柄。