通过方法转换,将array添加元素的方法进行转换,避免添加nil对象时出现crash情况。
#import <Foundation/Foundation.h>
@interface NSMutableArray (RunTime)
@end
#import "NSMutableArray+RunTime.h"
#import <objc/runtime.h>
@implementation NSMutableArray (RunTime)
#pragma mark - 方法替换
+ (void)load
{
// 方法1
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// 无效
// Class class = [self class];
// 有效
Class class = NSClassFromString(@"__NSArrayM");
SEL originalSelector = @selector(addObject:);
SEL swizzledSelector = @selector(addObjectSafe:);
Method originalMethod = class_getInstanceMethod(class, originalSelector);
Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
// judge the method named swizzledMethod is already existed.
BOOL didAddMethod = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
// if swizzledMethod is already existed.
if (didAddMethod)
{
class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
}
else
{
method_exchangeImplementations(originalMethod, swizzledMethod);
}
});
// 方法2
// 无效(异常:Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil')
// Class class = [self class];
// 有效
// Class class = NSClassFromString(@"__NSArrayM");
// Method oldMethod = class_getInstanceMethod(class, @selector(addObject:));
// Method newMethod = class_getInstanceMethod(class, @selector(addObjectSafe:));
// method_exchangeImplementations(oldMethod, newMethod);
}
- (void)addObjectSafe:(id)anObject
{
if (anObject)
{
[self addObjectSafe:anObject];
NSLog(@"添加成功");
}
else
{
NSLog(@"添加失败,不能添加 nil 对象");
}
}
@end