處理系統(tǒng)valueForUndefinedKey:類型的crash報(bào)錯(cuò)

背景

最近上線項(xiàng)目中使用UIVisualEffectView(高斯模糊)出現(xiàn)[<__NSArrayI 0x17000b630> valueForUndefinedKey:]: this class is not key value coding-compliant for the key gaussianBlur.錯(cuò)誤
初始化時(shí)出現(xiàn)下面錯(cuò)誤:


錯(cuò)誤日志.png

使用以下初始化方法:

- (UIVisualEffectView *)effectView{
    if(!_effectView){
        _effectView = [[UIVisualEffectView alloc] initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleDark]];
    }
    return _effectView;
}

該錯(cuò)誤主要在ios8系統(tǒng)下才會(huì)出現(xiàn)的個(gè)別情況。查找了一些資料,該問題應(yīng)該是系統(tǒng)bug. 那么就想如何避免該類型的報(bào)錯(cuò)導(dǎo)致crash.

處理方法

使用kvc和runtime機(jī)制防止程序出現(xiàn)意外的UnknownException類型的錯(cuò)誤。(轉(zhuǎn)移特定類型,如NSArray的valueForUndefinedKey: 和 setValue:forUndefinedKey:的具體實(shí)現(xiàn))

實(shí)現(xiàn)

為NSObject添加分類:NSObject+VFUK.
在分類中實(shí)現(xiàn)自定義實(shí)現(xiàn)過程:
NSObject+VFUK.h

//
//  NSObject+VFUK.h
//  BlockRedpag
//
//  Created by 何其燦 on 2019/1/3.
//  Copyright ? 2019 Lixiaoqian. All rights reserved.
//  處理系統(tǒng) valueForUndefinedKey:錯(cuò)誤

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface NSObject (VFUK)

///自定義valueForUndefinedKey:實(shí)現(xiàn)
+ (void)addCustomValueForUndefinedKeyImplementation:(IMP)handler;

@end

NS_ASSUME_NONNULL_END

NSObject+VFUK.m實(shí)現(xiàn):

//
//  NSObject+VFUK.m
//  BlockRedpag
//
//  Created by 何其燦 on 2019/1/3.
//  Copyright ? 2019 Lixiaoqian. All rights reserved.
//

#import "NSObject+VFUK.h"
#import <CoreData/CoreData.h>
#import <objc/message.h>

@implementation NSObject (VFUK)

+ (void)addCustomValueForUndefinedKeyImplementation:(IMP)handler{
    Class clazz = self;
    if (clazz == nil) {
        return;
    }
    if (clazz == [NSObject class] || clazz == [NSManagedObject class])
  {
        return;
    }
    
    SEL vfuk = @selector(valueForUndefinedKey:);
    SEL svfuk = @selector(setValue:forUndefinedKey:);
    
    @synchronized([NSObject class]){
        Method nsoMethod = class_getInstanceMethod([NSObject class], vfuk);
        Method nsmoMethod = class_getInstanceMethod([NSManagedObject class], vfuk);
        Method origMethod = class_getInstanceMethod(clazz, vfuk);
        
        Method set_nsoMethod = class_getInstanceMethod([NSObject class], svfuk);
        Method set_nsmoMethod = class_getInstanceMethod([NSManagedObject class], svfuk);
        Method set_origMethod = class_getInstanceMethod(clazz, svfuk);
        
        
        if (set_origMethod != set_nsoMethod && set_origMethod != set_nsmoMethod) {
            return;
        }
        if (origMethod != nsoMethod && origMethod != nsmoMethod) {
            return;
        }
        
        if(!class_addMethod(clazz, svfuk, handler, method_getTypeEncoding(set_nsmoMethod))) {
        }
        
        if(!class_addMethod(clazz, vfuk, handler, method_getTypeEncoding(nsoMethod))) {
        }
    }
    
}

@end

實(shí)現(xiàn)以上類目后,在AppDelegate.m中對指定類型進(jìn)行轉(zhuǎn)移,如NSArray,NSString等。

static id UnknownExceptionKeyIMP(id self, SEL cmd, NSString* inKey)
{
    NSLog(@"exception key:%@,class:%@", inKey, [self class]);
    return nil;
}


@implementation AppDelegate

+ (void)initialize
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        [NSArray addCustomValueForUndefinedKeyImplementation: (IMP)UnknownExceptionKeyIMP];
        [NSString addCustomValueForUndefinedKeyImplementation: (IMP)UnknownExceptionKeyIMP];
        [NSDictionary addCustomValueForUndefinedKeyImplementation: (IMP)UnknownExceptionKeyIMP];
        [CALayer addCustomValueForUndefinedKeyImplementation: (IMP)UnknownExceptionKeyIMP];
    });
}

添加之后,如果項(xiàng)目中再使用一些非法的valueForKey或setValue:forKey:方法時(shí),不至于崩潰閃退,從而可以避免一些系統(tǒng)NSUnknownException類型的報(bào)錯(cuò)。如下例子:

//不可變字典 進(jìn)行setValue:ForKey:操作
    NSDictionary *dict = [NSDictionary dictionary];
    [dict setValue:@"heqican" forKey:@"name"];
//不可變數(shù)組進(jìn)行setValue:forKey:操作
    NSArray *array = @[@"1",@"2"];
    [array setValue:@"松小寶" forKey:@"name"];
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • KVC KVC定義 KVC(Key-value coding)鍵值編碼,就是指iOS的開發(fā)中,可以允許開發(fā)者通過K...
    暮年古稀ZC閱讀 2,164評論 2 9
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對...
    cosWriter閱讀 11,135評論 1 32
  • KVC(Key-value coding)鍵值編碼,單看這個(gè)名字可能不太好理解。其實(shí)翻譯一下就很簡單了,就是指iO...
    我的夢工廠閱讀 901評論 1 8
  • 1.設(shè)計(jì)模式是什么? 你知道哪些設(shè)計(jì)模式,并簡要敘述?設(shè)計(jì)模式是一種編碼經(jīng)驗(yàn),就是用比較成熟的邏輯去處理某一種類型...
    龍飝閱讀 2,180評論 0 12
  • KVC(Key-valuecoding)鍵值編碼,單看這個(gè)名字可能不太好理解。其實(shí)翻譯一下就很簡單了,就是指iOS...
    榕樹頭閱讀 722評論 0 2