zoukankan      html  css  js  c++  java
  • 异常处理NSException的使用(思维篇)

    关于异常处理的使用的格式基本就是:

    @try {
    
    } @catch (NSException *exception) {
    
    } @finally {
    
    }

    通过这段时间对异常处理相关知识的整理,我觉得需要掌握以下几个方面的内容:

    1 要会创建NSException对象,并且会使用@throw抛出异常

    2 了解异常处理的作用

    使用@try进行异常处理,一开始会有类似下面两个问题弄不明白:

    1 既然异常发生了,程序一定会退出,那还需要@final逻辑干嘛,程序退出了一切都重新开始不就行了

    2 异常发生后,然后判断是属于哪种异常,使用@catch分别处理的意图是什么呢

     

    举个简单的例子,对数组越界访问(比如数组总共3个元素,取第4个元素就会产生异常)

    - (void)test {
        NSString *name = [self queryValue];
        NSLog(@">>>>>>>>>%@", name);
        if (!name) {
            NSLog(@">>>>>>>>>通知服务器取值失败");
        } else {
            NSLog(@">>>>>>>>>通知服务器取值成功");
        }
    }
    
    - (NSString *)queryValue {
        NSArray *arr = @[@"111", @"222", @"333"];
        NSString *string = [arr objectAtIndex:3];
        return string;
    }

    控制台打印的信息:

    2021-08-08 23:35:12.956564+0800 OCTestLine[22690:1921426] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** __boundsFail: index 3 beyond bounds [0 .. 2]'
    *** First throw call stack:
    (
        0   CoreFoundation                      0x00007fff2dd5ff53 __exceptionPreprocess + 250
        1   libobjc.A.dylib                     0x00007fff63e25835 objc_exception_throw + 48
        2   CoreFoundation                      0x00007fff2de22d3a _CFThrowFormattedException + 202
        3   CoreFoundation                      0x00007fff2de2a203 -[__NSArrayI getObjects:range:].cold.1 + 0
        4   CoreFoundation                      0x00007fff2dcbd061 -[__NSSingleObjectSetI member:] + 0
        5   OCTestLine                          0x0000000100000d97 -[PersonClass queryValue] + 135
        6   OCTestLine                          0x0000000100000c9c -[PersonClass test] + 44
        7   OCTestLine                          0x0000000100000c47 main + 87
        8   libdyld.dylib                       0x00007fff651882e5 start + 1
    )
    libc++abi.dylib: terminating with uncaught exception of type NSException
    (lldb) 

    关于这种越界取值的情况,程序会直接抛出异常,抛出异常的结果就是程序crash(崩溃),这在程序开发过程中相对于“错误”,“异常”导致crash更容易定位bug,这样直截了当地crash的确也没什么,定位bug、修改代码、重新运行就行了,因此在软件开发过程中,“异常处理”的确没什么用。但是如果有以下需求呢?

    1 程序闪退之前,我想把这个“异常”信息记录下来,或者记录在本地,或者上传记录在服务器上,方便后期修复优化代码;

    2 程序闪退之前,我想把一些“操作”做完,以确保整个系统的安全性;

    这样的需求并不过分,比如用户下载了已经发布的版本,使用过程中出现了闪退,肯定是需要进行crash统计的,方便程序员定位问题,腾讯Bugly就是基于此需求开发的框架。

    另外,使用异常处理有个现实情况是,当App出现异常闪退了,但是并没有真正的“杀死”进程,这个时候是可以继续使用该App的进程继续做其他操作的(比如上传异常信息到服务器)。

    {
        NSString *name;
    }
    
    - (void)test {
        @try {
            name = [self queryValue];
            NSLog(@">>>>>>>>>%@", name);
        } @catch (NSException *exception) {
            NSLog(@">>>>>>>>>%@", exception);
            for (int i = 1; i < 11; i++) {
                sleep(1);
                NSLog(@">>>>>>>>>将错误信息上传服务器进度:%d%%", i*10);
            }
        } @finally {
            for (int i = 10; i > 0; i--) {
                sleep(1);
                NSLog(@">>>>>>>>>退出程序倒计时:%d", i);
            }
            if (!name) {
                NSLog(@">>>>>>>>>通知服务器取值失败");
            } else {
                NSLog(@">>>>>>>>>通知服务器取值成功");
            }
        }
    }
    
    - (NSString *)queryValue {
        NSArray *arr = @[@"111", @"222", @"333"];
        NSString *string = [arr objectAtIndex:3];
        return string;
    }

    在控制台的打印结果如下:

    2021-08-09 00:00:47.686273+0800 OCTestLine[22920:1933899] >>>>>>>>>*** __boundsFail: index 3 beyond bounds [0 .. 2]
    2021-08-09 00:00:48.688200+0800 OCTestLine[22920:1933899] >>>>>>>>>将错误信息上传服务器进度:10%
    2021-08-09 00:00:49.693500+0800 OCTestLine[22920:1933899] >>>>>>>>>将错误信息上传服务器进度:20%
    2021-08-09 00:00:50.698861+0800 OCTestLine[22920:1933899] >>>>>>>>>将错误信息上传服务器进度:30%
    2021-08-09 00:00:51.704219+0800 OCTestLine[22920:1933899] >>>>>>>>>将错误信息上传服务器进度:40%
    2021-08-09 00:00:52.709532+0800 OCTestLine[22920:1933899] >>>>>>>>>将错误信息上传服务器进度:50%
    2021-08-09 00:00:53.714876+0800 OCTestLine[22920:1933899] >>>>>>>>>将错误信息上传服务器进度:60%
    2021-08-09 00:00:54.720185+0800 OCTestLine[22920:1933899] >>>>>>>>>将错误信息上传服务器进度:70%
    2021-08-09 00:00:55.725510+0800 OCTestLine[22920:1933899] >>>>>>>>>将错误信息上传服务器进度:80%
    2021-08-09 00:00:56.726721+0800 OCTestLine[22920:1933899] >>>>>>>>>将错误信息上传服务器进度:90%
    2021-08-09 00:00:57.732028+0800 OCTestLine[22920:1933899] >>>>>>>>>将错误信息上传服务器进度:100%
    2021-08-09 00:00:58.737385+0800 OCTestLine[22920:1933899] >>>>>>>>>退出程序倒计时:10
    2021-08-09 00:00:59.741825+0800 OCTestLine[22920:1933899] >>>>>>>>>退出程序倒计时:9
    2021-08-09 00:01:00.747129+0800 OCTestLine[22920:1933899] >>>>>>>>>退出程序倒计时:8
    2021-08-09 00:01:01.752443+0800 OCTestLine[22920:1933899] >>>>>>>>>退出程序倒计时:7
    2021-08-09 00:01:02.757756+0800 OCTestLine[22920:1933899] >>>>>>>>>退出程序倒计时:6
    2021-08-09 00:01:03.763067+0800 OCTestLine[22920:1933899] >>>>>>>>>退出程序倒计时:5
    2021-08-09 00:01:04.768387+0800 OCTestLine[22920:1933899] >>>>>>>>>退出程序倒计时:4
    2021-08-09 00:01:05.773704+0800 OCTestLine[22920:1933899] >>>>>>>>>退出程序倒计时:3
    2021-08-09 00:01:06.774743+0800 OCTestLine[22920:1933899] >>>>>>>>>退出程序倒计时:2
    2021-08-09 00:01:07.780073+0800 OCTestLine[22920:1933899] >>>>>>>>>退出程序倒计时:1
    2021-08-09 00:01:07.780251+0800 OCTestLine[22920:1933899] >>>>>>>>>通知服务器取值失败
    Program ended with exit code: 0

    关于控制台打印的信息,有两点说明:

    1 仔细看打印的时间,可以知道,异常发生后,app闪退后,后台进程并没有退出,在用户通过“多任务”进行删除app之前,依然可以运行代码做很多事;

    2 使用@try正常处理异常,程序是属于正常退出的,“Program ended with exit code:0”。

     

     

     

  • 相关阅读:
    对技术的态度
    码农提高工作效率
    为什么要使用String
    Java还是程序员的金饭碗
    为什么Java7开始在数字中使用下划线
    阿里云快速搭建一个静态网站
    IDEA中Springboot项目部署到阿里云linux服务器
    Linux环境下安装宝塔面板
    阿里云服务器的购买和配置以及搭建项目教程
    linux服务器上部署springboot项目,并让他持续运行到后台
  • 原文地址:https://www.cnblogs.com/cchHers/p/15116833.html
Copyright © 2011-2022 走看看