美文网首页
iOS 发生在Objective-C层(OC Exception

iOS 发生在Objective-C层(OC Exception

作者: Geniune | 来源:发表于2019-11-18 16:40 被阅读0次

    发生在Objective-C层的奔溃异常,称为:OC Exception

    1. NSException介绍

    如果说你对NSException这个类不了解,那这下面这张图的输出内容在开发过程中肯定经常和你见面:

    图片.png

    附导致上图中抛出错误的代码:

    NSMutableArray *array = [NSMutableArray array];
    NSString *strObj = nil;
    [array addObject:strObj];
    

    这样的错误是致命的,也就说在不做任何容错的情况下,程序直接Crash,也就是俗称”闪退“,解决这类iOS提供的SDK导致的崩溃异常可以使用NSSetUncaughtExceptionHandler来进行处理,附GitHub链接:

    https://github.com/minibear0523/UncaughtExceptionHandler

    但App奔溃的的原因还有内存访问错误、重复释放等问题,这些异常NSSetUncaughtExceptionHandler是无法处理的,因为这类错误发送的是SIGNAL。

    2. NSException处理

    苹果提供了NSError错误处理和NSException异常处理两种机制,NSError用来处理程序中可恢复的错误(通常情况下程序可以继续运行),而NSException用来处理不可恢复的错误(会导致程序终止的严重异常)

    在没有研究NSException之前,苹果开发一直有个令我非常疑惑的地方,就是Java中经常使用的try{****} catch{****},为什么在iOS代码中几乎见不到?这个得益于ARC自动内存管理,在大多数时候开发者并不需要手动管理内存(并不是绝对安全),但是如果你面对某段有潜在奔溃风险的代码,则可以使用try catch来捕捉异常:

    @try {
        //放有可能会出现异常错误的代码
    }
    @catch (NSException *exception) {
        //只有try块中的代码出现了异常才会执行,用于匹配处理抛出的异常
    }
    @finally {
        //无论是否抛出异常,都会执行的代码
    }
    

    整个执行过程会有以下几种情况:

    1. try块代码没有发生异常,则程序会执行try块内、finally块内、finally块之后的代码;
    2. try块代码发生了异常,并且有catch捕捉匹配的异常,则程序在try块内发生异常后剩下的代码将不再执行,跳转到catch块内并抛出NSException对象;
    3. try块代码发生了异常,并且有catch没有能匹配捕捉,则程序会执行try和finally块中的代码,并将异常返回给调用者,finally块之后的代码也不执行。

    通过try catch方法可以解决很多问题,上面addObject插入nil对象的奔溃也可以被妥善解决:

        @try {
            [array addObject:strObj];
        }
        @catch (NSException *exception) {
            //打印exception输出:
            //exception.name = NSInvalidArgumentException
            //exception.reason = *** -[NSArrayM insertObject:atIndex:]: object cannot be nil
            //还可以通过exception.callStackSymbols查看函数堆栈,发现对应异常错误发生在哪个类中的哪一行
        }
        @finally {
            
        }
    

    3. Foundation常见奔溃异常

    Foundation是我们在开发过程中最常使用的框架,与CoreFoundation不同Foundation提供的是Objective-C接口,他主要提供了:数据类型(数组、字典、集合等)、字符串、时间、日期、URL、线程、RunLoop等。

    这也造成了很多异常的发送,比如:

    • 数组越界
    • 可变数组插入空对象
    • KVO在addObserver后不remove
    • 调用对象方法找不到selector对应的函数时,消息转发

    可以利用Runtime特性在Category使用新函数替换掉系统的存在异常风险的方法

    4. 在发布到App Store的版本中,通过上述手段捕捉的异常如何得知?

    由于我们将异常捕获了,所以程序不会产生奔溃现象,那么在这样的情况下作为开发者如何收集这些被捕获的异常呢?显然像友盟、Bugly这样的第三方SDK根本不管用了,其实完全可以自给自足,我是通过腾讯Mars框架中的Xlog来实现的,并且人家的框架生成的.xlog文件还支持非对称加密,保证了在网络传输过程中即使被截获也不用担心泄漏。
    附上Mars的GitHub链接:

    https://github.com/Tencent/mars

    如果本文对你有所帮助,记得点击一下喜欢哈

    相关文章

      网友评论

          本文标题:iOS 发生在Objective-C层(OC Exception

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