在开发过程中,很多时候崩溃总是防不胜防,上线前我们也对程序测了又测,可上线后还是经常遇到崩溃提示unrecognized selector sent to instance。崩溃的原因很多,预防的方法也要对症下药,这里我们就对因找不到方法而崩溃来进行治疗


首先
我们如果能在开发过程中预知这里要崩溃,我们肯定就会做处理,但往往天不遂人愿,比如使用了一个iOS10新出的方法,但没做判断,而程序支持到了iOS9,又正好公司没有iOS9的手机,这时候匆匆上线肯定会收集一批因找不到该方法而崩溃的日志。
那要怎么预防呢,我们可以使用iOS的消息转发机制,对没有实现的方法进行处理,用到的技术包括:


    1. category
2. method swizze
3. 消息转发(快速转发)


以下是代码实现:
NSObject+KXNoCrash.h

                                
#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface NSObject (KXNoCrash)

@end

NS_ASSUME_NONNULL_END
                            

NSObject+KXNoCrash.m

                                
#import "NSObject+KXNoCrash.h"

#import <objc/runtime.h>


@implementation NSObject (KXNoCrash)

// 用来替换的方法 可以在这里统计崩溃的日志
void methodB(id self, SEL _cmd, id msg) {
    NSLog(@"this should be a crash:%@", msg);
}

+ (void)load
{
    // 实现方法交换
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Method oriMethod = class_getInstanceMethod([self class], @selector(forwardingTargetForSelector:));
        Method tarMethod = class_getInstanceMethod([self class], @selector(kxForwardingTargetForSelector:));
        method_exchangeImplementations(oriMethod, tarMethod);
    });
}

// 对不存在的方法进行处理,动态添加方法
- (id)kxForwardingTargetForSelector:(SEL)aSelector
{
    if ([self respondsToSelector:aSelector]) {
        return [self kxForwardingTargetForSelector:aSelector];
    }else {
        class_addMethod([NSObject class], aSelector, (IMP)methodB, "@v:@");
        NSLog(@"%@,%@", NSStringFromClass([self class]),  NSStringFromSelector(aSelector));
        NSObject *obj = [NSObject alloc];
        return obj;
    }
}

@end
                            
将该这两个文件放到项目中,就能防止崩溃了。
创作不易,转载请注明出处:http://limming.site/blog/ios/ios-nocrash.html
谢谢浏览。