AvoidCrash
This framework can effective avoid crash by potential error code. For example : If you insert a nil into a mutable array, this framework can avoid crash and note you that where cause crash.
Install / Use
/learn @chenfanfang/AvoidCrashREADME
停更说明
由于作者工作时间的问题,目前作者已经暂时停止维护AvoidCrash,已经有多个系统版本没有兼容,大家可以根据自己项目所需要进行改造。
建议大家只使用
NSArray *noneSelClassStrings = @[
@"NSNull",
@"NSNumber",
@"NSString",
@"NSDictionary",
@"NSArray"
];
[AvoidCrash setupNoneSelClassStringsArr:noneSelClassStrings];
不建议大家使用前缀的方式来处理
疑惑解答
很多开发小伙伴经常私信问我一些问题:
1、若集成了腾讯Bugly或者友盟等等异常搜集的SDK,AvoidCrash会影响到它们的异常搜集吗?
2、为什么集成了AvoidCrash还是会报unrecognized selector sent to instance的异常?
关于疑惑的解答,请点击AvoidCrash疑惑解答
前言
一个已经发布到AppStore上的App,最忌讳的就是崩溃问题。为什么在开发阶段或者测试阶段都不会崩溃,而发布到AppStore上就崩溃了呢?究其根源,最主要的原因就是数据的错乱。特别是 服务器返回数据的错乱,将严重影响到我们的App。
Foundation框架存在许多潜在崩溃的危险
- 将 nil 插入可变数组中会导致崩溃。
- 数组越界会导致崩溃。
- 根据key给字典某个元素重新赋值时,若key为 nil 会导致崩溃。
- ......
AvoidCrash简介
- 这个框架利用runtime技术对一些常用并且容易导致崩溃的方法进行处理,可以有效的防止崩溃。
- 并且打印出具体是哪个方法会导致崩溃,让你快速定位导致崩溃的代码。
- 你可以获取到原本导致崩溃的主要信息<由于这个框架的存在,并不会崩溃>,进行相应的处理。比如:
- 你可以将这些崩溃信息发送到自己服务器。
- 你若集成了第三方崩溃日志收集的SDK,比如你用了腾讯的Bugly,你可以上报自定义异常。
- 或许你会问就算防止了崩溃,但是所获取到的数据变成nil或者并非是你所需要的数据,这又有什么用?对于防止崩溃,我的理解是,宁愿一个功能不能用,都要让app活着,至少其他功能还能用。
下面先来看下防止崩溃的效果吧
可导致崩溃的代码
NSString *nilStr = nil;
NSArray *array = @[@"chenfanfang", nilStr];
- 若没有AvoidCrash来防止崩溃,则会直接崩溃,如下图

- 若有AvoidCrash来防止崩溃,则不会崩溃,并且会将原本会崩溃情况的详细信息打印出来,如下图

Installation【安装】
From CocoaPods【使用CocoaPods】
pod 'AvoidCrash', '~> 2.5.2'
Manually【手动导入】
- Drag all source files under floder
AvoidCrashto your project.【将AvoidCrash文件夹中的所有源代码拽入项目中】 - 对 NSMutableArray+AvoidCrash.m 文件进行 -fno-objc-arc 设置(若使用CocoaPods集成则无需手动配置),配置过程如下图:

使用方法
- AvoidCrash使用注意点讲解
//让AvoidCrash生效方法有两个becomeEffective和makeAllEffective,若都不调用,则AvoidCrash就不起作用
[AvoidCrash becomeEffective]; //【默认不开启 对”unrecognized selector sent to instance”防止崩溃的处理】
//若要开启对对”unrecognized selector sent to instance”防止崩溃的处理】,请使用
//[AvoidCrash makeAllEffective],使用注意点,请看AvoidCrash.h中的描述,必须配合[AvoidCrash setupNoneSelClassStringsArr:]的使用
//【建议在didFinishLaunchingWithOptions最初始位置调用】[AvoidCrash makeAllEffective]
/*
[AvoidCrash becomeEffective]和[AvoidCrash makeAllEffective]是全局生效。若你只需要部分生效,你可以单个进行处理,比如:
[NSArray avoidCrashExchangeMethod];
[NSMutableArray avoidCrashExchangeMethod];
.................
.................
*/
- 在AppDelegate的didFinishLaunchingWithOptions方法中的最初始位置添加如下代码,让AvoidCrash生效
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//启动防止崩溃功能(注意区分becomeEffective和makeAllEffective的区别)
//具体区别请看 AvoidCrash.h中的描述
//建议在didFinishLaunchingWithOptions最初始位置调用 上面的方法
[AvoidCrash makeAllEffective];
//若出现unrecognized selector sent to instance导致的崩溃并且控制台输出:
//-[__NSCFConstantString initWithName:age:height:weight:]: unrecognized selector sent to instance
//你可以将@"__NSCFConstantString"添加到如下数组中,当然,你也可以将它的父类添加到下面数组中
//比如,对于部分字符串,继承关系如下
//__NSCFConstantString --> __NSCFString --> NSMutableString --> NSString
//你可以将上面四个类随意一个添加到下面的数组中,建议直接填入 NSString
NSArray *noneSelClassStrings = @[
@"NSString"
];
[AvoidCrash setupNoneSelClassStringsArr:noneSelClassStrings];
//监听通知:AvoidCrashNotification, 获取AvoidCrash捕获的崩溃日志的详细信息
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(dealwithCrashMessage:) name:AvoidCrashNotification object:nil];
return YES;
}
- 若你想要获取崩溃日志的所有详细信息,只需添加通知的监听,监听的通知名为:AvoidCrashNotification
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[AvoidCrash becomeEffective];
//监听通知:AvoidCrashNotification, 获取AvoidCrash捕获的崩溃日志的详细信息
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(dealwithCrashMessage:) name:AvoidCrashNotification object:nil];
return YES;
}
- (void)dealwithCrashMessage:(NSNotification *)note {
//注意:所有的信息都在userInfo中
//你可以在这里收集相应的崩溃信息进行相应的处理(比如传到自己服务器)
NSLog(@"%@",note.userInfo);
}
- 下面通过打断点的形式来看下userInfo中的信息结构,看下包含了哪些信息

- 再看下控制台输出日志来看下userInfo中的包含了哪些信息

目前可以防止崩溃的方法有
- unrecognized selector sent to instance
1. 对”unrecognized selector sent to instance”防止崩溃的处理
- NSArray
-
1. NSArray的快速创建方式 NSArray *array = @[@"chenfanfang", @"AvoidCrash"]; //这种创建方式其实调用的是2中的方法 -
2. +(instancetype)arrayWithObjects:(const id _Nonnull __unsafe_unretained *)objects count:(NSUInteger)cnt -
3. 通过下标获取元素 array[100]、[array objectAtIndex:100]- (id)objectAtIndex:(NSUInteger)index
-
4. - (NSArray *)objectsAtIndexes:(NSIndexSet *)indexes -
5. - (void)getObjects:(__unsafe_unretained id _Nonnull *)objects range:(NSRange)range
-
- NSMutableArray
1. 通过下标获取元素 array[100]、[array objectAtIndex:100]- (id)objectAtIndex:(NSUInteger)index
2. - (void)setObject:(id)obj atIndexedSubscript:(NSUInteger)idx3. - (void)removeObjectAtIndex:(NSUInteger)index4. - (void)insertObject:(id)anObject atIndex:(NSUInteger)index5. - (NSArray *)objectsAtIndexes:(NSIndexSet *)indexes6. - (void)getObjects:(__unsafe_unretained id _Nonnull *)objects range:(NSRange)range
- NSDictionary
1. NSDictionary的快速创建方式 NSDictionary *dict = @{@"frameWork" : @"AvoidCrash"}; //这种创建方式其实调用的是2中的方法2. +(instancetype)dictionaryWithObjects:(const id _Nonnull __unsafe_unretained *)objects forKeys:(const id<NSCopying> _Nonnull __unsafe_unretained *)keys count:(NSUInteger)cnt
- NSMutableDictionary
1. - (void)setObject:(id)anObject forKey:(id<NSCopying>)aKey2. - (void)removeObjectForKey:(id)aKey
- NSString
1. - (unichar)characterAtIndex:(NSUInteger)index2. - (NSString *)substringFromIndex:(NSUInteger)from3. - (NSString *)substringToIndex:(NSUInteger)to {4. - (NSString *)substringWithRange:(NSRange)range {5. - (NSString *)stringByReplacingOccurrencesOfString:(NSString *)target withString:(NSString *)replacement6. - (NSString *)stringByReplacingOccurrencesOfString:(NSString *)target withString:(NSString *)replacement options:(NSStringCompareOptions)options range:(NSRange)searchRange7. - (NSString *)stringByReplacingCharactersInRange:(NSRange)range withString:(NSString *)replacement
- NSMutableString
1. 由于NSMutableString是继承于NSString,所以这里和NSString有些同样的方法就不重复写了2. - (void)replaceCharactersInRange:(NSRange)range withString:(NSString *)aString3. - (void)insertString:(NSString *)aString atIndex:(NSUInteger)loc4. - (void)deleteCharactersInRange:(NSRange)range
- KVC
1.- (void)setValue:(id)value forKey:(NSString *)key2.- (void)setValue:(id)value forKeyPath:(NSString *)keyPath3.- (void)setValue:(id)value forUndefinedKey:(NSString *)key //这个方法一般用来重写,不会主动调用4.- (void)setValuesForKeysWithDictionary:(NSDictionary<NSString *,id> *)keyedValues
- NSAttributedString
1.- (instancetype)initWithString:(NSString *)str2.- (instancetype)initWithAttributedString:(NSAttributedString *)attrStr3.- (instancetype)initWithString:(NSString *)str attributes:(NSDictionary<NSString *,id> *)attrs
- NSMutableAttributedString
1.- (instancetype)initWithString:(NSString *)str2.- (instancetype)initWithString:(NSString *)str attributes:(NSDictionary<NSString *,id> *)attrs
更新
2018-03-14 (pod 2.5.2)
- Fix bug #45 #46 #51 (NSMutableDictionary Set nil Object will Crash.)
2017-12-26 (pod 2.5.1)
- 兼容iOS11的处理
2017-08-11
- 优化对”unrecognized selector sent to instance”防止崩溃的处理
2017-07-25
- 优化对”unrecognized selector sent to instance”防止崩溃的处理
2017-07-23
- 增加对”unrecognized selector sent to instance”防止崩溃的处理
2016-12-19
- Release环境下取消控制台的输出。
2016-12-1
-
处理数组的类簇问题,提高兼容性,不论是由于array[100]方式,还是[array objectAtIndex:100]方式 获取数组中的某个元素操作不当而导致的crash,都能被拦截防止崩溃。
-
上一个版本只能防止array[100]导致的崩溃,不能防止[array objectAtIndex:100]导致的崩溃。
-
统一对线程进行处理,监听通知AvoidCrashNotification后,不论是在主线程导致的crash还是在子线程导致的crash,监听通知的方法统一在"主线程"中。
-
上一个版本中,在哪个线程导致的crash, 则监听通知的方法就在哪个线程中。
-
新增防止崩溃 (NSArray、NSMutableArray)
- (void)getObjects:(__unsafe_unretained id _Nonnull *)objects range:(NSRange)range
2016-11-29
- 修复在键盘弹出状态下,按Home键进入后台会导致崩溃的bug。
- 新增防止崩溃(N
Related Skills
node-connect
339.1kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
83.8kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
339.1kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
commit-push-pr
83.8kCommit, push, and open a PR
