在開發(fā)過程中,總是會(huì)遇到各種Exception化焕,在此總結(jié)一些常見的Exception。
NSInvalidArgumentException
錯(cuò)誤類型 | NSInvalidArgumentException |
---|---|
log輸出 | unrecognized selector sent to instance xxxx |
錯(cuò)誤釋義 | 給實(shí)體對象發(fā)送了不認(rèn)識的消息,即對象調(diào)用方法出錯(cuò) |
錯(cuò)誤基本原因 | Objective-C的方法調(diào)用其實(shí)是基于消息傳遞機(jī)制,并且是動(dòng)態(tài)編譯誉结。因此在編譯階段不會(huì)進(jìn)行類和方法的綁定,而是在運(yùn)行時(shí)執(zhí)行綁定操作券躁。當(dāng)類的方法沒有實(shí)現(xiàn)或?qū)ο蟊惶崆皉elease時(shí)惩坑,這個(gè)問題會(huì)在運(yùn)行時(shí)表現(xiàn)出來,從而導(dǎo)致App崩潰 |
常見場景
場景1 給對象發(fā)送消息時(shí):
[self performSelector:@selector(testException:) withObject:@"string"];
-(void)testException {
NSLog(@"%s",__func__);
}
錯(cuò)誤分析:給對象發(fā)消息的時(shí)候嘱朽,該消息是帶形參的旭贬,而實(shí)現(xiàn)的方法卻不帶形參怔接,因此產(chǎn)生了異常搪泳。
場景2 在集合中:
NSMutableArray *array = [NSMutableArray array];
[array addObject:nil];
錯(cuò)誤分析:當(dāng)企圖給集合插入nil值的時(shí)候,實(shí)際上調(diào)用的是[__NSArrayM insertObject: atIndex: ]扼脐,根據(jù)CFArray的源碼推斷岸军,在該方法里面,對插入的對象進(jìn)行了斷言操作(僅僅是猜想瓦侮,未能找到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作為設(shè)計(jì)模式的一種,貫穿于App中肚吏。通常我們會(huì)將delegate定義為id類型方妖,也就意味著,任何對象都有可能成為代理罚攀。成為代理的實(shí)例可能只是遵守了協(xié)議党觅,但是卻沒對協(xié)議的方法進(jìn)行具體實(shí)現(xiàn)雌澄。在上面的場景中,有可能代理對象并沒有實(shí)現(xiàn)sendRequest:方法杯瞻,此時(shí)調(diào)用sendRequest:方法就會(huì)出現(xiàn)崩潰镐牺。
正確的操作
在給delegate發(fā)送消息之前應(yīng)該進(jìn)行respondsToSelector判斷
-(BOOL)doRequest:(NSURL *)url {
...
if (delegate && [delegate respondsToSelector:@selector(sendRequest:)]) {
...
return [delegate sendRequest:url];
}
...
return NO;
}
NSRangeException
錯(cuò)誤類型 | NSRangeException |
---|---|
log輸出 | 1.index 2 beyond bounds [0 .. 1] 2.index x beyond bounds for .. |
錯(cuò)誤釋義 | 1.索引序號2超出0~1區(qū)間 2.索引序號超出... |
常見場景
場景1 插入或獲取對象:
NSMutableArray *array = [NSMutableArray array];
[array addObject:@"one"];
[array addObject:@"two"];
[array objectAtIndex:2];
錯(cuò)誤分析:當(dāng)試圖從數(shù)組中獲得一個(gè)對象的時(shí)候,索引大于自身容量魁莉,因而引起該異常睬涧。同樣在插入的時(shí)候,不正確的索引值也會(huì)引發(fā)這個(gè)問題旗唁。
場景2 截取字符串:
NSMutableString *str = [[NSMutableString alloc] initWithString:@"one"];
[str substringFromIndex:5];
錯(cuò)誤分析:當(dāng)試圖截取字符串的時(shí)候畦浓,起始索引大于字符串本身長度。
NSGenericException
錯(cuò)誤類型 | NSGenericException |
---|---|
log輸出 | xxxxxx was mutated while being enumerated. |
錯(cuò)誤釋義 | 對象xxxxxx在枚舉的時(shí)候是不可變的 |
常見場景
場景1 遍歷的時(shí)候添加或移除對象:
NSMutableArray *array = [NSMutableArray arrayWithObjects:@"1",@"2",@"3",nil];
for (NSString *string in array) {
[array addObject:@"4"];
// [array removeObject:@"66"];
}
錯(cuò)誤分析:在遍歷的時(shí)候检疫,對集合進(jìn)行了插入/刪除操作宅粥。
NSFileHandleOperationException
錯(cuò)誤類型 | NSFileHandleOperationException |
---|---|
log輸出 | Bad file descriptor |
錯(cuò)誤釋義 | 錯(cuò)誤的文件描述符 |
常見場景
場景1 對文件進(jìn)行操作:
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];
錯(cuò)誤分析:企圖對文件進(jìn)行寫操作,但獲取句柄時(shí)电谣,請求的確是只讀句柄秽梅。