iOS常见Crash解决方法

常见crash

  • 数组越界
  • 插入nil对象
  • 无法识别的selector
  • 其他异常

数组越界

这里主要由NSArray或者NSMutableArray访问了不在范围内的对象造成的。对于Inmutable数组基本就涉及到一个objectAtIndex:。

 NSArray *array = @[@"test"];
 id object = array[1];//抛出异常                  1.

而对于Mutable数组有修改和删除就主要涉及到setObject:atIndex,insertObject:atIndex:和removeObject:atIndex:来着。

 NSMutableArray *mArray = [NSMutableArray arrayWithArray:@[@"test"]];
[mArray insertObject:@"asdf" atIndex:2]; //抛出异常  2.
[mArray removeObejctAtIndex:2];   //异常          3.

插入nil对象

这类问题基本上是出现在数组、字典的初始化中,或者在插入对象时出现。
id obj = nil;
NSArray *array = @[obj,@"test"];  //异常  1

NSString *key = nil;
NSString *value = nil;
NSDictionary *dict = @{key:value}; //异常 2

无法识别的selector

其他异常

针对上面的2个问题,我这里是通过category+swizzle的方式进行的。由于无法识别selector,还没有还一点的正常途径来解决。所以就不说了。这里就弄几段代码。




@implementation NSObject (KLSwizzle)

+ (void) kl_swizzleInstanceSelector:(SEL)originalSelector
                 withNewSelector:(SEL)newSelector
{
    Method originalMethod = class_getInstanceMethod(self, originalSelector);
    Method newMethod = class_getInstanceMethod(self, newSelector);

    BOOL methodAdded = class_addMethod([self class],
                                       originalSelector,
                                       method_getImplementation(newMethod),
                                       method_getTypeEncoding(newMethod));

    if (methodAdded){
        class_replaceMethod([self class],
                            newSelector,
                            method_getImplementation(originalMethod),
                            method_getTypeEncoding(originalMethod));
    }else {
        method_exchangeImplementations(originalMethod, newMethod);
    }

}

+ (void)kl_swizzleClassSelector:(SEL)originalSelector
                withNewSelector:(SEL)newSelector{
    Method originalMethod = class_getClassMethod(self, originalSelector);
    Method newMethod = class_getClassMethod(self, newSelector);
    method_exchangeImplementations(originalMethod, newMethod);

}

@end

@implementation NSArray (KLException)

+ (void)load{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Class cls = [[self array] class];
        [cls kl_swizzleInstanceSelector:@selector(objectAtIndex:) withNewSelector:KLHookedSel(objectAtIndex:)];
        [self kl_swizzleClassSelector:@selector(arrayWithObjects:count:) withNewSelector:KLHookedSel(arrayWithObjects:count:)];
    });
}



- (id)KLHookedMethod(objectAtIndex:(NSUInteger)index){
    __autoreleasing id instance = nil;
    if([self checkRange:index]){
        @try{
            instance = [self KLHookedMethod(objectAtIndex:)index];
         }
        @catch (NSException *exception) {
            KLLogError(@"exception:%@",exception);
        }
    }else{
       KLLogError(@"catch out of range:%lul in %@ ",(unsigned long)index,self);
    }

    return instance;
}

- (BOOL)checkRange:(NSUInteger)index{
    return [self count] > index;
}

+ (void) _kl_removeObjectFromArray:(const id [])objects at:(NSUInteger) index count:(NSUInteger)cnt{
    __unsafe_unretained id* objs = (__unsafe_unretained id*) objects;
    for(NSUInteger i=index;i<cnt&&(i+1)<cnt;++i){
        objs[i] = objs[i+1];
    }
}
+ (instancetype)KLHookedMethod(arrayWithObjects:(const id [])objects count:(NSUInteger)cnt){
    NSUInteger count = cnt;
    for(NSUInteger i = 0; i < count; ++i){
        if(!objects[i]) {
            KLLogError(@"insert nil at %d",i);
            [self _kl_removeObjectFromArray:objects at:i count:count--];
        }
    }

    return [self KLHookedMethod(arrayWithObjects:objects count:count)];
}

@end

@implementation NSDictionary (KLException)

+ (void)load{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        [self kl_swizzleClassSelector:@selector(dictionaryWithObjects:forKeys:count:) withNewSelector:KLHookedSel(dictionaryWithObjects:forKeys:count:)];
    });
}

+ (void) _kl_removePairObjects:(const id [])objects keys:(const id <NSCopying> [])keys at:(NSUInteger) index count:(NSUInteger)cnt{
    __unsafe_unretained id* objs = (__unsafe_unretained id*) objects;
    __unsafe_unretained id* tmpKeys = (__unsafe_unretained id*) keys;
    for(NSUInteger i=index;i<cnt&&(i+1)<cnt;++i){
        objs[i] = objs[i+1];
    }

    for(NSUInteger i=index;i<cnt&&(i+1)<cnt;++i){
        tmpKeys[i] = tmpKeys[i+1];
    }

}
+ (instancetype)KLHookedMethod(dictionaryWithObjects:(const id [])objects forKeys:(const id <NSCopying> [])keys count:(NSUInteger)cnt){
    NSUInteger count = cnt;
    for(NSUInteger i = 0; i < count; ++i){
        if(!objects[i] || !keys[i]) {
            KLLogError(@"insert nil at %d to dictionary",i);
            [self _kl_removePairObjects:objects keys:keys at:i count:count--];
        }
    }

    return [self KLHookedMethod(dictionaryWithObjects:objects forKeys:keys count:count)];
}
@end
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值