美文网首页超棒文集杏仁丶的iOS学习专题iOS开发技术
iOS被开发者遗忘在角落的NSException-其实它很强大

iOS被开发者遗忘在角落的NSException-其实它很强大

作者: chenfanfang | 来源:发表于2016-10-06 22:50 被阅读7222次

NSException是什么?

最熟悉的陌生人,这是我对NSException的概述,为什么这么说呢?其实很多开发者接触到NSException的频率非常频繁,但很多人都不知道什么是NSException,不知道如何使用NSException。下面从一张截图开始讲起NSException。

崩溃截图.png

上面这张图想必大家都不陌生吧!(卧槽,程序又崩溃了)。

其实控制台输出的日志信息就是NSException产生的,一旦程序抛出异常,程序就会崩溃,控制台就会有这些崩溃日志。


NSException的基本用法

下面代码就会让你的程序崩溃

    //异常的名称
    NSString *exceptionName = @"自定义异常";
    //异常的原因
    NSString *exceptionReason = @"我长得太帅了,所以程序崩溃了";
    //异常的信息
    NSDictionary *exceptionUserInfo = nil;
    
    NSException *exception = [NSException exceptionWithName:exceptionName reason:exceptionReason userInfo:exceptionUserInfo];
    
    NSString *aboutMe = @"太帅了";
    
    if ([aboutMe isEqualToString:@"太帅了"]) {
        //抛异常
        @throw exception;
    }

崩溃截图如下

自定义异常崩溃截图.png

为什么说NSException很强大

NSException掌控着程序的生命,程序的崩溃就是NSException来控制的,你说NSException不强大吗?那为何要NSException来使程序崩溃呢?其实主要的出发点是让开发者认识到哪里的代码有问题。

下面说两个NSException的实用技巧吧

  • 1、 若自己封装一套SDK,若要提示哪里出错,那么就可以使用NSException。就像上面NSException的基本用法中的代码一样。
  • 2、可以用来捕获异常,防止程序的崩溃。当你意识到某段代码可能存在崩溃的危险,那么你就可以通过捕获异常来防止程序的崩溃。代码如下
    NSString *nilStr = nil;
    NSMutableArray *arrayM = [NSMutableArray array];
    
    @try {
        //如果@try中的代码会导致程序崩溃,就会来到@catch
        
        //将一个nil插入到可变数组中,这行代码肯定有问题
        [arrayM addObject:nilStr];
    }
    @catch (NSException *exception) {
        //如果@try中的代码有问题(导致崩溃),就会来到@catch
        
        //在这里你可以进行相应的处理操作
        
        //如果你要抛出异常(让程序崩溃),就写上 @throw exception
        
    }
    @finally {
        
        //@finally中的代码是一定会执行的
        
        //你可以在这里进行一些相应的操作
    }
  • 3、最最实用的一个技术点就是利用 分类(category) + runtime + 异常的捕获 来防止Foundation一些常用方法使用不当而导致的崩溃。其原理就是利用category、runtime来交换两个方法,并且在方法中捕获异常进行相应的处理。(这里需要了解一些关于runtime的知识点,若对runtime不熟悉的朋友,可以先去了解下runtime的方法交换)。下面直接附上大概的使用方法。

添加分类,利用runtime交换方法

//
//  NSMutableArray+Extension.m
//  categoryTest
//
//  Created by mac on 16/10/6.
//  Copyright © 2016年 chenfanfang. All rights reserved.
//

#import "NSMutableArray+Extension.h"

#import <objc/runtime.h>

@implementation NSMutableArray (Extension)

+ (void)load {
    
    Class arrayMClass = NSClassFromString(@"__NSArrayM");
    
    //获取系统的添加元素的方法
    Method addObject = class_getInstanceMethod(arrayMClass, @selector(addObject:));
    
    //获取我们自定义添加元素的方法
    Method avoidCrashAddObject = class_getInstanceMethod(arrayMClass, @selector(avoidCrashAddObject:));
    
    //将两个方法进行交换
    //当你调用addObject,其实就是调用avoidCrashAddObject
    //当你调用avoidCrashAddObject,其实就是调用addObject
    method_exchangeImplementations(addObject, avoidCrashAddObject);
}

- (void)avoidCrashAddObject:(id)anObject {
    
    @try {
        [self avoidCrashAddObject:anObject];//其实就是调用addObject
    }
    @catch (NSException *exception) {
        
        //能来到这里,说明可变数组添加元素的代码有问题
        //你可以在这里进行相应的操作处理
        
        NSLog(@"异常名称:%@   异常原因:%@",exception.name, exception.reason);
    }
    @finally {
        //在这里的代码一定会执行,你也可以进行相应的操作
    }
}

@end

验证上面的代码的确可以捕获异常,并且不会崩溃

    NSString *nilStr = nil;
    NSMutableArray *arrayM = [NSMutableArray array];
    [arrayM addObject:nilStr];

控制台输出截图如下

捕获到的异常信息.png

利用category + runtime + 异常的捕获 来写一个防止崩溃的框架

相关文章

  • iOS被开发者遗忘在角落的NSException(转)

    原文地址iOS被开发者遗忘在角落的NSException-其实它很强大 - CocoaChina_让移动开发更简单...

  • iOS被开发者遗忘在角落的NSException-其实它很强大

    NSException是什么? 最熟悉的陌生人,这是我对NSException的概述,为什么这么说呢?其实很多开发...

  • 被遗忘在角落

    近来坐地铁总喜欢在车头或者车尾,原因自然是人少不挤。在这样一个人声鼎沸的节日里不被挤得脚不落地自是应该高兴的,可我...

  • 被遗忘在角落的

    午后的散步已成为一种习惯 长长的走廊来回踱步 只让阳光从窗口的缝隙溜进来 躲在雨水打不着的地方 隔着玻璃窗 小心翼...

  • 被遗忘在角落的雨伞

    所有的不幸, 都是荒废时间的报应。

  • 被遗忘在角落的天使

    在西北地区的农村里只有一些孩子,我们称之位留守儿童,他们的爸妈一年都在在打工,只留他们和爷爷奶奶生活。 今年六一儿...

  • 被遗忘在角落的惊喜

    月初在网上买了三袋蘑菇,发货来的时候根本就看不出来什么,就是三袋土而已。 之前买过一次,什么都没种出来,后来就丢了...

  • 被遗忘在角落的芦荟

    2014年夏天,记得那时房刚装修好,我们打算先“凉凉”,散散有害气体,就没计划搬家,为了净化空气,媳妇学邻居,特意...

  • 被遗忘的角落

    年华似水 青春从指缝间流过 曾经自信我的 渐渐开始失落 开始习惯性的躲在一个角落 一天 我又走进一个角落 一个被遗...

  • 被遗忘的角落

    在这繁华的和平时代,你也许无法想象,有那么一个角落,似乎曾经被遗忘过,他们整天的生活是那么的天真无邪。有这...

网友评论

  • 哈哈哈士奇XHB:oc的try catch处理不当有内存泄露,官方也不推荐开发者使用
  • 7afe30d6ef13:666666666
  • 开飞机的叔客:学习了!
  • NAN先生的喵:mark一下
  • 给你快乐:又学到了,收藏点赞!
  • jianshu小赵:写的很好 那请问例如有些 统计 例如有梦统计 或者bugly 怎么做到 异常监控的
  • 863c73f31933:楼上,问一下,当NSException抛出的时候如何获取是那个类,那个方法,那一行代码导致的,这个你那边有研究不?
    e087aa6ed421:@SunlightInMyLif
    放到主线程中试试
    dispatch_async(dispatch_get_main_queue(), ^{
    });
    863c73f31933:@李宏伟 这个类闪退在内存地址里面的闪退和闪退在主线程里面的闪退,这两种的都能捕获嘛?我这边怎么碰到捕获不了的情况
    e087aa6ed421: NSDictionary *dict = @{@"类名": [NSString stringWithFormat:@"%@",[self class]],@“哪一行":[NSString stringWithFormat:@"%ld",(long)__LINE__],@"方法名":[NSString stringWithFormat:@"%s",__PRETTY_FUNCTION__]};
  • 大牛在郑州:想问个问题,正常的iOS的程序中,任何一个对象调用任何一个方法,在执行这个方法的时候都会 进行这个
    @try @Catch 吗?
  • 泥巴锦:不错
  • 鸟人扎墨客:写的非常好,已经收藏了
  • 鼻毛长长:1.可以使用热修复
    2.服务返回数据的问题,应该是服务的责任吧?
    3.加判断的话全部代码得有多少If啊?而且在多线程的情况下,加判断也未必好使
    4.如果感觉这段代码要出问题的话,为什么不好好审视重新写呢?
    chenfanfang:@鼻毛长长 你好,首先肯定你的想法。但有一点你有没有意识到,若发布版本的崩溃造成的影响有多严重!你的想法我可以理解,的确服务器占很大部分的责任。但移动端做送错处理是一个很好的习惯。你可以查看我另一篇博客,关于用runtime一次性拦截错误。:relaxed::relaxed:谢谢你的提议

本文标题:iOS被开发者遗忘在角落的NSException-其实它很强大

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