Foundation框架防奔溃

2019-01-10  本文已影响4人  Geniune

源码:https://github.com/Geniune/SafeProtector
用法:将三个文件夹拖入工程即可,无需import任何头文件

基本很多奔溃都出在下面几个问题上:

  1. 数组越界、空指针
  2. 字典空指针
  3. 服务器和原生本地字段数据类型不匹配
  4. 调用UIButton setTitle:或UILabel setText:时,使用非NSString类型对象赋值等

由于OC动态运行时语言的特性在不做容错的情况下,开发者有时也很难确保对象类型是否与预期的一致,也很容易导致奔溃现象发生

例如解决”数组越界“这个问题,思路如下:

分析数组取值的方法,有下面两种:

  1. [array objectAtIndex:10] (objectAtIndex:)
  2. 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做判断)

如果本文对你有所帮助记得点个喜欢哈

上一篇 下一篇

猜你喜欢

热点阅读