源码:https://github.com/Geniune/SafeProtector
用法:将三个文件夹拖入工程即可,无需import任何头文件
基本很多奔溃都出在下面几个问题上:
- 数组越界、空指针
- 字典空指针
- 服务器和原生本地字段数据类型不匹配
- 调用UIButton setTitle:或UILabel setText:时,使用非NSString类型对象赋值等
由于OC动态运行时语言的特性在不做容错的情况下,开发者有时也很难确保对象类型是否与预期的一致,也很容易导致奔溃现象发生
例如解决”数组越界“这个问题,思路如下:
分析数组取值的方法,有下面两种:
- [array objectAtIndex:10] (objectAtIndex:)
- array[10](objectAtIndexedSubscript:)
创建NSArray分类(Category),在+load函数中重指向两个取值方法,注意使用dispatch_once保证线程安全且只执行一次
+ (void)load
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self exchangeInstance:objc_getClass("__NSArrayI") selector:@selector(objectAtIndex:)withSwizzledSelector:@selector(safe_objectAtIndexI:)];
[self exchangeInstance:objc_getClass("__NSArrayI") selector:@selector(objectAtIndexedSubscript:) withSwizzledSelector:@selector(safe_objectAtIndexedSubscriptI:)];
});
}
然后再实现重定向的方法函数:
- (instancetype)safe_objectAtIndexI:(NSUInteger)index
{
id object = nil;
@try {
object = [self safe_objectAtIndexI:index];
} @catch (NSException *exception) {
LSSafeProtectionCrashLog(exception,LSSafeProtectorCrashTypeNSArray);
} @finally {
return object;
}
}
- (instancetype)safe_objectAtIndexedSubscriptI:(NSUInteger)index
{
id object = nil;
@try {
object = [self safe_objectAtIndexedSubscriptI:index];
} @catch (NSException *exception) {
LSSafeProtectionCrashLog(exception,LSSafeProtectorCrashTypeNSArray);
} @finally {
return object;
}
}
@end
只要保证工程中包含该NSArray分类即可(无需import),使用如下:
NSArray *array = @[@"Tom", @"John", @"Merry"];
[array objectAtIndex:4];
这时程序不会直接奔溃,控制台报错如下:
图片.png
其他NSMutableArray和NSDictionary的容错实现类似,这里不逐个赘述。
想重新放开让程序直接奔溃只需将NSObject+SafeProtector.m中47行中的assert();方法注释回来即可
(注意在上架前检查或根据debug/release做判断)
如果本文对你有所帮助记得点个喜欢哈
网友评论