数组越界是常见的崩溃 , 崩溃日记是类似这样的 :
Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArray0 objectAtIndex:]: index 22 beyond bounds for empty NSArray'
网上也找过怎么解决,但是都不是太彻底, 由于 NSArray是一个类簇,需要把所有的入口都封住才算完美 . 方法还是很常见的,用了runtime的方法替换 . 然后 给NSArray加类别 , 部分核心代码:
@implementation NSArray (SafeIndex)
+ (void)load{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// NSArray 是一个类簇,具体有三个子类__NSArray0,__NSSingleObjectArrayI,__NSArrayI,
// 还有一个__NSPlaceholderArray是占位的,不实际使用
// 对__NSArray0,__NSSingleObjectArrayI来说,下面三种调用的同一个方法objectAtIndex
/** 对__NSArrayI,__NSArrayM来说,objectAtIndex 和 objectAtIndexedSubscript 有不同的实现,
array[22]调用了objectAtIndexedSubscript */
// [array objectAtIndex:22];
// [array objectAtIndexedSubscript:22];
// array[22];
[objc_getClass("__NSArray0") gl_swizzleMethod:@selector(objectAtIndex:) withMethod:@selector(emptyObjectIndex:)];
[objc_getClass("__NSSingleObjectArrayI") gl_swizzleMethod:@selector(objectAtIndex:) withMethod:@selector(singleObjectIndex:)];
[objc_getClass("__NSArrayI") gl_swizzleMethod:@selector(objectAtIndex:) withMethod:@selector(safe_arrObjectIndex:)];
[objc_getClass("__NSArrayI") gl_swizzleMethod:@selector(objectAtIndexedSubscript:) withMethod:@selector(safe_objectAtIndexedSubscript:)];
[objc_getClass("__NSArrayM") gl_swizzleMethod:@selector(objectAtIndex:) withMethod:@selector(safeObjectIndex:)];
[objc_getClass("__NSArrayM") gl_swizzleMethod:@selector(objectAtIndexedSubscript:) withMethod:@selector(mutableArray_safe_objectAtIndexedSubscript:)];
[objc_getClass("__NSArrayM") gl_swizzleMethod:@selector(insertObject:atIndex:) withMethod:@selector(safeInsertObject:atIndex:)];
[objc_getClass("__NSArrayM") gl_swizzleMethod:@selector(addObject:) withMethod:@selector(safeAddObject:)];
});
}
- (id)emptyObjectIndex:(NSInteger)index {
NSLog(@"__NSArray0 取一个空数组 objectAtIndex , 崩溃") ;
return nil;
}
- (id)singleObjectIndex:(NSInteger)index {
if (index >= self.count || index < 0) {
NSLog(@"__NSSingleObjectArrayI 取一个不可变单元素数组时越界 objectAtIndex , 崩溃") ;
return nil;
}
return [self singleObjectIndex:index];
}
- (id)safe_arrObjectIndex:(NSInteger)index{
if (index >= self.count || index < 0) {
NSLog(@"__NSArrayI 取不可变数组时越界 objectAtIndex , 崩溃") ;
return nil;
}
return [self safe_arrObjectIndex:index];
}
- (id)safe_objectAtIndexedSubscript:(NSInteger)index{
if (index >= self.count || index < 0) {
NSLog(@"__NSArrayI 取不可变数组时越界 objectAtIndexedSubscript , 崩溃") ;
return nil;
}
return [self safe_objectAtIndexedSubscript:index];
}
- (id)mutableArray_safe_objectAtIndexedSubscript:(NSInteger)index{
if (index >= self.count || index < 0) {
NSLog(@"__NSArrayM 取可变数组时越界 objectAtIndexedSubscript , 崩溃") ;
return nil;
}
return [self mutableArray_safe_objectAtIndexedSubscript:index];
}
- (id)safeObjectIndex:(NSInteger)index{
if (index >= self.count || index < 0) {
NSLog(@"__NSArrayM 取可变数组时越界 objectAtIndex , 崩溃") ;
return nil;
}
return [self safeObjectIndex:index];
}
- (void)safeInsertObject:(id)object atIndex:(NSUInteger)index{
if (index>self.count) {
NSLog(@"__NSArrayM 添加元素越界 insertObject:atIndex: , 崩溃") ;
return ;
}
if (object == nil) {
NSLog(@"__NSArrayM 添加空元素 insertObject:atIndex: , 崩溃") ;
return ;
}
[self safeInsertObject:object atIndex:index];
}
- (void)safeAddObject:(id)object {
if (object == nil) {
NSLog(@"__NSArrayM 添加空元素 addObject , 崩溃") ;
return ;
}
[self safeAddObject:object];
}
@end
下载地址: https://download.csdn.net/download/u014600626/10400062
或者 cocoa上的 : http://code.cocoachina.com/view/137085