美文网首页iOS沉淀
iOS 常见Exception

iOS 常见Exception

作者: XIAOHANG | 来源:发表于2018-03-29 21:07 被阅读16次

    在开发过程中,总是会遇到各种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];
    

    错误分析:企图对文件进行写操作,但获取句柄时,请求的确是只读句柄。

    相关文章

      网友评论

        本文标题:iOS 常见Exception

        本文链接:https://www.haomeiwen.com/subject/lyfnqftx.html