程序崩溃对于app来说是最致命的bug,而数组越界便是其中最重要的原因之一。我们可以应用Method Swizzling知识来避免这一问题。
1.我们来创建一个类别,继承于NSArray:
2.然后在.m文件中导入 objc/runtime.h头文件
#import "NSArray+EM.h"
#import <objc/runtime.h>
@implementation NSArray (EM)
+(void)load {
Method fromMethod = class_getInstanceMethod(objc_getClass("__NSArrayI"), @selector(objectAtIndex:));
Method toMethod = class_getInstanceMethod(objc_getClass("__NSArrayI"), @selector(em_objectAtIndex:));
method_exchangeImplementations(fromMethod, toMethod);
}
- (void)em_objectAtIndex:(NSUInteger)index {
if (self.count - 1 < index) {
@try {
return[self em_objectAtIndex:index];
}
@catch (NSException *exception) {
NSLog(@"-------- %s Crash Because Method %s -------\n",class_getName(self.class),__func__);
NSLog(@"%@", [exception callStackSymbols]);
}
@finally {
}
}else {
return [self em_objectAtIndex:index];
}
}
@end
细心的人会发现,下面这个方法会导致递归,其实不会的。
这实际上是运用了方法替换,当我们在其他类中 调用NSArray的objectAtIndex方法时,会被自动替换为执行em_objectAtIndex:方法,而当我们调用em_objectAtIndex:方法时,会被替换为执行objectAtIndex:方法。我们也可以用这种方法同样解决NSMutableArray。
#import "NSMutableArray+EM.h"
#import <objc/runtime.h>
@implementation NSMutableArray (EM)
+(void)load {
Method fromMethod =
class_getInstanceMethod(objc_getClass("__NSArrayM"), @selector(objectAtIndex:));
Method toMethod =
class_getInstanceMethod(objc_getClass("__NSArrayM"), @selector(em_objectAtIndex:));
method_exchangeImplementations(fromMethod, toMethod);
}
- (void)em_objectAtIndex:(NSUInteger)index {
if (self.count - 1 < index) {
@try {
return[self em_objectAtIndex:index];
}
@catch (NSException *exception) {
NSLog(@"-------- %s Crash Because Method %s -------\n",class_getName(self.class),__func__);
NSLog(@"%@", [exception callStackSymbols]);
}
@finally {
}
}else {
return [self em_objectAtIndex:index];
}
}
@end
还可以判断NSMutableDictionary 的value值是否为nil
#import "NSMutableDictionary+EM.h"
#import <objc/runtime.h>
@implementation NSMutableDictionary (EM)
+ (void)load {
Method fromMethod = class_getInstanceMethod(objc_getClass("__NSDictionaryM"), @selector(setObject:forKey:));
Method toMethod = class_getInstanceMethod(objc_getClass("__NSDictionaryM"), @selector(em_setObject:forKey:));
method_exchangeImplementations(fromMethod, toMethod);
}
- (void)em_setObject:(id)emObject forKey:(NSString *)key {
if (emObject == nil) {
@try {
[self em_setObject:emObject forKey:key];
}
@catch (NSException *exception) {
NSLog(@"---------- %s Crash Because Method %s ----------\n", class_getName(self.class), __func__);
NSLog(@"%@", [exception callStackSymbols]);
emObject = [NSString stringWithFormat:@""];
[self em_setObject:emObject forKey:key];
}
@finally {}
}else {
[self em_setObject:emObject forKey:key];
}
}
@end
下面我们列举一些常用的类簇的“真身”:
注:转载自 MiAo_EM的博客