常常會看到這樣的崩潰日誌-[__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