Objective-C中异常处理

何为异常?

我的简单理解是:程序可以编译、运行,但是在某些特定的执行环境下会导致程序运行终止,也就是我们常说的崩溃或者闪退现象。

如何处理?

我们要抓住这个导致程序运行终止的代码,然后采取合理的方式将其处理掉。Objective-C提供了异常的处理机制

    @try {
        <#Code that can potentially throw an exception#>
    } @catch (NSException *exception) {
        <#Handle an exception thrown in the @try block#>
    }

有如下例子:

 

1、接下来,我们定义一个Person类

//
//  Person.h
//  MyObjective-C
//
//  Created by ZhaiKun on 2017/10/11.
//  Copyright © 2017年 ZhaiKun. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface Person : NSObject

- (void)run;

@end

在Person类中声明了一个run方法

 

2、再看Person类的实现

//
//  Person.m
//  MyObjective-C
//
//  Created by ZhaiKun on 2017/10/11.
//  Copyright © 2017年 ZhaiKun. All rights reserved.
//

#import "Person.h"

@implementation Person

@end

在Person类的实现代码中,没有实现run方法

 

3、接下来在程序的入口函数中对run方法进行调用

//
//  main.m
//  ExceptionDeal 异常处理
//
//  Created by ZhaiKun on 2017/10/11.
//  Copyright © 2017年 ZhaiKun. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Person.h"

int main(int argc, const char * argv[]) {
    
    Person *person = [Person new];
    [person run];
    
    NSLog(@"程序执行到了这里");
    
    return 0;
}

程序运行到[person run]时,就终止了运行,调试信息显示:run方法声明了,但是没有实现

2017-10-11 10:03:53.177952+0800 ExceptionDeal[812:23032] -[Person run]: unrecognized selector sent to instance 0x100406730
2017-10-11 10:03:53.178930+0800 ExceptionDeal[812:23032] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Person run]: unrecognized selector sent to instance 0x100406730'
*** First throw call stack:
(
	0   CoreFoundation                      0x00007fffb6f012cb __exceptionPreprocess + 171
	1   libobjc.A.dylib                     0x00007fffcbd1948d objc_exception_throw + 48
	2   CoreFoundation                      0x00007fffb6f82f04 -[NSObject(NSObject) doesNotRecognizeSelector:] + 132
	3   CoreFoundation                      0x00007fffb6e73755 ___forwarding___ + 1061
	4   CoreFoundation                      0x00007fffb6e732a8 _CF_forwarding_prep_0 + 120
	5   ExceptionDeal                       0x0000000100000f26 main + 70
	6   libdyld.dylib                       0x00007fffcc5ff235 start + 1
	7   ???                                 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb) 

4、对这个异常进行处理,使程序可以继续运行

//
//  main.m
//  ExceptionDeal 异常处理
//
//  Created by ZhaiKun on 2017/10/11.
//  Copyright © 2017年 ZhaiKun. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Person.h"

int main(int argc, const char * argv[]) {
    
    Person *person = [Person new];
    
    @try {
        //将可能发生异常的代码写在@try块中
        [person run];//一旦发生异常,立即执行@catch块中的代码,不会执行@try块中发生异常代码处之后的代码
        NSLog(@"我是处于异常后面的代码");
    } @catch (NSException *exception) {
        //确定异常已经发生,执行@catch块中的代码。如果@try块中的代码没有发生异常,是不会执行@catch块中的代码的
        NSLog(@"这里是处理异常");
    }
    
    NSLog(@"程序执行到了这里");
    
    return 0;
}

程序运行结果:

2017-10-11 10:22:36.727478+0800 ExceptionDeal[913:27826] -[Person run]: unrecognized selector sent to instance 0x1002032b0
2017-10-11 10:22:36.728071+0800 ExceptionDeal[913:27826] 这里是处理异常
2017-10-11 10:22:36.728109+0800 ExceptionDeal[913:27826] 程序执行到了这里
Program ended with exit code: 0

5、验证没有异常时不会执行@catch块中的代码,实现Person类中的run方法

//
//  Person.m
//  MyObjective-C
//
//  Created by ZhaiKun on 2017/10/11.
//  Copyright © 2017年 ZhaiKun. All rights reserved.
//

#import "Person.h"

@implementation Person

- (void)run{
    NSLog(@"实现了run方法");
}

@end

程序运行结果:

2017-10-11 10:29:33.763648+0800 ExceptionDeal[967:29474] 实现了run方法
2017-10-11 10:29:33.763909+0800 ExceptionDeal[967:29474] 我是处于异常后面的代码
2017-10-11 10:29:33.763935+0800 ExceptionDeal[967:29474] 程序执行到了这里
Program ended with exit code: 0

在@try块中,没有异常时,依次执行了@try块中的所有代码,直接跳过了@catch块

6、@catch块参数说明

    @catch (NSException *exception) {
       
    }

exception 指针对象,通过它可以拿到发生异常的原因。添加打印异常信息的代码

    @catch (NSException *exception) {
        //确定异常已经发生,执行@catch块中的代码。如果@try块中的代码没有发生异常,是不会执行@catch块中的代码的
        NSLog(@"这里是处理异常");
        NSLog(@"发生异常的原因:%@", exception);
    }

程序运行结果:

2017-10-11 10:45:46.946998+0800 ExceptionDeal[1044:33191] -[Person run]: unrecognized selector sent to instance 0x100504590
2017-10-11 10:45:46.947636+0800 ExceptionDeal[1044:33191] 这里是处理异常
2017-10-11 10:45:46.947709+0800 ExceptionDeal[1044:33191] 发生异常的原因:-[Person run]: unrecognized selector sent to instance 0x100504590
2017-10-11 10:45:46.947741+0800 ExceptionDeal[1044:33191] 程序执行到了这里
Program ended with exit code: 0

7、@finally处理机制说明:位于@try{ }@catch{ }的后面

    @try {
        <#Code that can potentially throw an exception#>
    } @catch (NSException *exception) {
        <#Handle an exception thrown in the @try block#>
    } @finally {
        <#Code that gets executed whether or not an exception is thrown#>
    }

在入口函数中增加@finally块

//
//  main.m
//  ExceptionDeal 异常处理
//
//  Created by ZhaiKun on 2017/10/11.
//  Copyright © 2017年 ZhaiKun. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Person.h"

int main(int argc, const char * argv[]) {
    
    Person *person = [Person new];

    @try {
        //将可能发生异常的代码写在@try块中
        [person run];//一旦发生异常,立即执行@catch块中的代码,不会执行@try块中发生异常代码处之后的代码
        NSLog(@"我是处于异常后面的代码");
    } @catch (NSException *exception) {
        //确定异常已经发生,执行@catch块中的代码。如果@try块中的代码没有发生异常,是不会执行@catch块中的代码的
        NSLog(@"这里是处理异常");
        NSLog(@"发生异常的原因:%@", exception);
    }@finally {
        //无论@try块中是否有异常,都会执行这里的代码
        NSLog(@"I am finally!");
    }
    
    NSLog(@"程序执行到了这里");
    
    return 0;
}

模拟发生异常时的运行结果:

2017-10-11 10:57:44.240396+0800 ExceptionDeal[1141:36516] -[Person run]: unrecognized selector sent to instance 0x100202330
2017-10-11 10:57:44.241212+0800 ExceptionDeal[1141:36516] 这里是处理异常
2017-10-11 10:57:44.241259+0800 ExceptionDeal[1141:36516] 发生异常的原因:-[Person run]: unrecognized selector sent to instance 0x100202330
2017-10-11 10:57:44.241286+0800 ExceptionDeal[1141:36516] I am finally!
2017-10-11 10:57:44.241301+0800 ExceptionDeal[1141:36516] 程序执行到了这里
Program ended with exit code: 0

模拟没有异常出现时的运行结果:

2017-10-11 10:58:37.252254+0800 ExceptionDeal[1177:36918] 实现了run方法
2017-10-11 10:58:37.252422+0800 ExceptionDeal[1177:36918] 我是处于异常后面的代码
2017-10-11 10:58:37.252447+0800 ExceptionDeal[1177:36918] I am finally!
2017-10-11 10:58:37.252465+0800 ExceptionDeal[1177:36918] 程序执行到了这里
Program ended with exit code: 0

得出结论:无论在@try块中是否有异常,程序最终都会执行@finally块中的代码

 

注意:@try、、、@catch对异常的处理是有一定的局限性的,也就是说这个东东是不能处理所有的异常的,典型的例子就是做除法运算时分母为0的情况。那么我们又怎么样对它不能处理的异常进行处理呢?推荐的方法是:进行逻辑判断处理。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值