iOS 數組越界,防Crash處理,性能優化 —— HERO博客

常常會看到這樣的崩潰日誌-[__NSArrayM objectAtIndex:]: index4 beyond bounds [0 ..1],數組越界。

舉個列子:

    int index = 3;
    NSArray *array = @[@"z", @"x", @"c"];
    [array objectAtIndex:index];

這段代碼執行會崩潰,數組越界,解決辦法有很多,比如我們可以嘗試增加一個條件判斷:

    int index = 3;
    NSArray *array = @[@"z", @"x", @"c"];
    if (index < array.count) {
        [array objectAtIndex:index];
    }

或者使用try...catch捕獲異常

    int index = 3;
    NSArray *array = @[@"z", @"x", @"c"];
    @try {
        //可能拋出異常的代碼
        [array objectAtIndex:index];
    }
    @catch (NSException *exception) {
        //處理異常
        NSLog(@"exception: %@", exception.reason);
    }
    @finally {
        //finally代碼塊是可選的,如果寫了,不管有沒有異常,block內的代碼都會被執行
        NSLog(@"finally");
    }


上面方法已經可以避免crash,爲了避免冗餘的代碼,寫一個NSArray的分類,利用runtime替換NSArray的對象方法objectAtIndex:,在這裏進行判斷,捕獲異常:

#import <Foundation/Foundation.h>

@interface NSArray (Crash)

@end

/*** ---------------分割線--------------- ***/ 

#import "NSArray+Crash.h"
#import <objc/runtime.h>

@implementation NSArray (Crash)

+ (void)load
{
    [super load];
    
    //替換不可變數組方法
    Method oldObjectAtIndex = class_getInstanceMethod(objc_getClass("__NSArrayI"), @selector(objectAtIndex:));
    Method newObjectAtIndex = class_getInstanceMethod(objc_getClass("__NSArrayI"), @selector(objectAtSafeIndex:));
    method_exchangeImplementations(oldObjectAtIndex, newObjectAtIndex);
    
    //替換可變數組方法
    Method oldMutableObjectAtIndex = class_getInstanceMethod(objc_getClass("__NSArrayM"), @selector(objectAtIndex:));
    Method newMutableObjectAtIndex =  class_getInstanceMethod(objc_getClass("__NSArrayM"), @selector(mutableObjectAtSafeIndex:));
    method_exchangeImplementations(oldMutableObjectAtIndex, newMutableObjectAtIndex);
}

- (id)objectAtSafeIndex:(NSUInteger)index
{
    if (index > self.count - 1 || !self.count) {
        @try {
            return [self objectAtSafeIndex:index];
        }
        @catch (NSException *exception) {
            NSLog(@"exception: %@", exception.reason);
            return nil;
        }
        
    }else {
        return [self objectAtSafeIndex:index];
    }
}

- (id)mutableObjectAtSafeIndex:(NSUInteger)index
{
    if (index > self.count - 1 || !self.count) {
        @try {
            return [self mutableObjectAtSafeIndex:index];
        }
        @catch (NSException *exception) {
            NSLog(@"exception: %@", exception.reason);
            return nil;
        }
        
    }else {
        return [self mutableObjectAtSafeIndex:index];
    }
}

@end


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章