美文网首页
处理系统valueForUndefinedKey:类型的cras

处理系统valueForUndefinedKey:类型的cras

作者: 爱迪生的小跟班 | 来源:发表于2019-01-03 14:24 被阅读0次

    背景

    最近上线项目中使用UIVisualEffectView(高斯模糊)出现[<__NSArrayI 0x17000b630> valueForUndefinedKey:]: this class is not key value coding-compliant for the key gaussianBlur.错误
    初始化时出现下面错误:


    错误日志.png

    使用以下初始化方法:

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

    该错误主要在ios8系统下才会出现的个别情况。查找了一些资料,该问题应该是系统bug. 那么就想如何避免该类型的报错导致crash.

    处理方法

    使用kvc和runtime机制防止程序出现意外的UnknownException类型的错误。(转移特定类型,如NSArray的valueForUndefinedKey: 和 setValue:forUndefinedKey:的具体实现)

    实现

    为NSObject添加分类:NSObject+VFUK.
    在分类中实现自定义实现过程:
    NSObject+VFUK.h

    //
    //  NSObject+VFUK.h
    //  BlockRedpag
    //
    //  Created by 何其灿 on 2019/1/3.
    //  Copyright © 2019 Lixiaoqian. All rights reserved.
    //  处理系统 valueForUndefinedKey:错误
    
    #import <Foundation/Foundation.h>
    
    NS_ASSUME_NONNULL_BEGIN
    
    @interface NSObject (VFUK)
    
    ///自定义valueForUndefinedKey:实现
    + (void)addCustomValueForUndefinedKeyImplementation:(IMP)handler;
    
    @end
    
    NS_ASSUME_NONNULL_END
    
    

    NSObject+VFUK.m实现:

    //
    //  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
    
    

    实现以上类目后,在AppDelegate.m中对指定类型进行转移,如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];
        });
    }
    

    添加之后,如果项目中再使用一些非法的valueForKey或setValue:forKey:方法时,不至于崩溃闪退,从而可以避免一些系统NSUnknownException类型的报错。如下例子:

    //不可变字典 进行setValue:ForKey:操作
        NSDictionary *dict = [NSDictionary dictionary];
        [dict setValue:@"heqican" forKey:@"name"];
    
    //不可变数组进行setValue:forKey:操作
        NSArray *array = @[@"1",@"2"];
        [array setValue:@"松小宝" forKey:@"name"];
    

    相关文章

      网友评论

          本文标题:处理系统valueForUndefinedKey:类型的cras

          本文链接:https://www.haomeiwen.com/subject/mjufrqtx.html