美文网首页
valueForKeyPath 奔溃

valueForKeyPath 奔溃

作者: BabyNeedCare | 来源:发表于2020-09-22 11:38 被阅读0次

昨天产品反馈了一个奔溃事件, 因为是做职业教育的, 刚好奔溃在课程上, 因此这里做处理总结。

请问下面代码会奔溃吗?

    NSArray *dataArrays = 
@[
        @{@"code": @"ab", @"name": @"apple"},        
        @{@"code": @"cd", @"name": @"flame"}    
    ];

    NSLog(@"----%@---%@",[dataArrays valueForKeyPath:@"name123455"], [[dataArrays valueForKeyPath:@"name123455"] class]);

打印结果

2020-09-22 11:29:04.134991+0800 mjfail[7041:137274] ----(
    "<null>",
    "<null>"
)---__NSArrayI

不会奔溃, 只是返回的是<null>类型的数组


那么假设是一个模型对象数组呢?

创建Person类, 只有2个属性, code, name

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface Person : NSObject

@property (copy, nonatomic) NSString *code;

@property (copy, nonatomic) NSString *name;

@end

NS_ASSUME_NONNULL_END

NSArray *dataArrays = @[
    
    @{@"code": @"ab", @"name": @"apple"},
    
    @{@"code": @"cd", @"name": @"flame"}
    
];


NSArray *data = [Person mj_objectArrayWithKeyValuesArray:dataArrays];

NSLog(@"%@", [data valueForKeyPath:@"点点滴滴"]);

这次会奔溃吗?

2020-09-22 11:31:12.927584+0800 mjfail[7073:139529] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<Person 0x60000330ad80> valueForUndefinedKey:]: this class is not key value coding-compliant for the key 点点滴滴.'
*** First throw call stack:
(
    0   CoreFoundation                      0x00007fff23c4f02e __exceptionPreprocess + 350
    1   libobjc.A.dylib                     0x00007fff50b97b20 objc_exception_throw + 48
    2   CoreFoundation                      0x00007fff23c4ebf9 -[NSException raise] + 9
    3   Foundation                          0x00007fff256f3f57 -[NSObject(NSKeyValueCoding) valueForUndefinedKey:] + 225
    4   Foundation                          0x00007fff256f2bca -[NSObject(NSKeyValueCoding) valueForKey:] + 317
    5   Foundation                          0x00007fff256f4abb -[NSArray(NSKeyValueCoding) valueForKey:] + 411
    6   Foundation                          0x00007fff256f4e6a -[NSArray(NSKeyValueCoding) valueForKeyPath:] + 416
    7   mjfail                              0x0000000100b2bc7b -[ViewController viewDidLoad] + 459
    8   UIKitCore                           0x00007fff471cdb25 -[UIViewController _sendViewDidLoadWithAppearanceProxyObjectTaggingEnabled] + 83
    9   UIKitCore                           0x00007fff471d2a7e -[UIViewController loadViewIfRequired] + 1084
    10  UIKitCore                           0x00007fff471d2e9b -[UIViewController view] + 27
    11  UIKitCore                           0x00007fff4788742d -[UIWindow addRootViewControllerViewIfPossible] + 150
    12  UIKitCore                           0x00007fff47886ae4 -[UIWindow _updateLayerOrderingAndSetLayerHidden:actionBlock:] + 232
    13  UIKitCore                           0x00007fff47887ba1 -[UIWindow _setHidden:forced:] + 362
    14  UIKitCore                           0x00007fff4789af4d -[UIWindow _mainQueue_makeKeyAndVisible] + 42
    15  UIKitCore                           0x00007fff47aa669d -[UIWindowScene _makeKeyAndVisibleIfNeeded] + 202
    16  UIKitCore                           0x00007fff46ddbe81 +[UIScene _sceneForFBSScene:create:withSession:connectionOptions:] + 1405
    17  UIKitCore                           0x00007fff4784bf1a -[UIApplication _connectUISceneFromFBSScene:transitionContext:] + 1018
    18  UIKitCore                           0x00007fff4784c25c -[UIApplication workspace:didCreateScene:withTransitionContext:completion:] + 304
    19  UIKitCore                           0x00007fff473b920d -[UIApplicationSceneClientAgent scene:didInitializeWithEvent:completion:] + 361
    20  FrontBoardServices                  0x00007fff36555225 -[FBSSceneImpl _callOutQueue_agent_didCreateWithTransitionContext:completion:] + 442
    21  FrontBoardServices                  0x00007fff3657b598 __86-[FBSWorkspaceScenesClient sceneID:createWithParameters:transitionContext:completion:]_block_invoke.154 + 102
    22  FrontBoardServices                  0x00007fff3655fd05 -[FBSWorkspace _calloutQueue_executeCalloutFromSource:withBlock:] + 220
    23  FrontBoardServices                  0x00007fff3657b229 __86-[FBSWorkspaceScenesClient sceneID:createWithParameters:transitionContext:completion:]_block_invoke + 355
    24  libdispatch.dylib                   0x0000000100e74d48 _dispatch_client_callout + 8
    25  libdispatch.dylib                   0x0000000100e77cb9 _dispatch_block_invoke_direct + 300
    26  FrontBoardServices                  0x00007fff365a143e __FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ + 30
    27  FrontBoardServices                  0x00007fff365a112c -[FBSSerialQueue _queue_performNextIfPossible] + 441
    28  FrontBoardServices                  0x00007fff365a163b -[FBSSerialQueue _performNextFromRunLoopSource] + 22
    29  CoreFoundation                      0x00007fff23bb2221 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
    30  CoreFoundation                      0x00007fff23bb214c __CFRunLoopDoSource0 + 76
    31  CoreFoundation                      0x00007fff23bb197c __CFRunLoopDoSources0 + 268
    32  CoreFoundation                      0x00007fff23bac62f __CFRunLoopRun + 1263
    33  CoreFoundation                      0x00007fff23babe16 CFRunLoopRunSpecific + 438
    34  GraphicsServices                    0x00007fff38438bb0 GSEventRunModal + 65
    35  UIKitCore                           0x00007fff4784fb48 UIApplicationMain + 1621
    36  mjfail                              0x0000000100b2c0b4 main + 116
    37  libdyld.dylib                       0x00007fff51a1dc25 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

奔溃很彻底。

专成对象后, 再使用valueForKeyPath, 找不到对应的属性, 就会奔溃。

可是项目中有很多地方使用到了valueForKeyPath, 在每个对应模型中加指定属性, 范围太大, 方法不可取。

那么, 我想到用运行时拦截方法。

  1. 创建NSArray的分类

  2. 在.m文件中实现交换方法


#import "NSArray+updateArrays.h"
#import <objc/runtime.h>
#import "MJExtension.h"
@implementation NSArray (updateArrays)

+ (void)load {
    
    Class class = [self class];
    SEL originalSelector = NSSelectorFromString(@"valueForKeyPath:");
    SEL swizzledSelector = NSSelectorFromString(@"transiValueForKeyPath:");
    Method originalMethod = class_getInstanceMethod(class, originalSelector);
    Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);

    BOOL didAddMethod =
    class_addMethod(class,
                    originalSelector,
                    method_getImplementation(swizzledMethod),
                    method_getTypeEncoding(swizzledMethod));

    if (didAddMethod) {
        class_replaceMethod(class,
                            swizzledSelector,
                            method_getImplementation(originalMethod),
                            method_getTypeEncoding(originalMethod));
    } else {
        method_exchangeImplementations(originalMethod, swizzledMethod);
    }

}

- (nullable id)transiValueForKeyPath:(NSString *)keyPath {
    
    __block BOOL isHaveKeyPath = NO;

    [self enumerateObjectsUsingBlock:^(NSObject * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {

        if ([obj.mj_keyValues.allKeys containsObject:keyPath]){

            isHaveKeyPath = YES;

            *stop = YES;
        }
    }];

    if (isHaveKeyPath) {

        return [self transiValueForKeyPath:keyPath];

    } else {

        return nil;
    }
}


@end

这样就可以完美解决同类型的问题了!

相关文章

  • valueForKeyPath 奔溃

    昨天产品反馈了一个奔溃事件, 因为是做职业教育的, 刚好奔溃在课程上, 因此这里做处理总结。 请问下面代码会奔溃吗...

  • DYLD, Library not loaded: /usr/l

    奔溃日志 奔溃表现:iOS12.1 及以下启动奔溃奔溃日志: 解决方法:关闭bitcode,重新打包上传appst...

  • iOS-千奇百怪的奔溃

    App 上线后,我们最怕的应该就是异常奔溃了。常见的奔溃类型分两种:信号可捕获奔溃、信号不可捕获奔溃,前者比较典型...

  • 奔溃

    送表弟们去上学的路上,听说刚才忘了拿《斗罗大陆》,却又接着说可以向同学借。我的内心立即奔溃了,满满的无力感! 当初...

  • 奔溃

    我总是想不让自己在乎别人的眼光,所以我总是在街上很自在,不担心自己的丑态被别人看到,我也经常对女友这么说,不要在意...

  • 奔溃

    工作到奔溃 加班到晚上八九点 没有人会理解你的苦楚,下班回家星空相伴,人与人之间的关系脆弱到分崩离析,工作后发现身...

  • 奔溃

    为什么当知道这个结果,我却奔溃了?原来不被期待的事情却偏偏来了,心里是那样的抵触。

  • 奔溃

    这次我是真的奔溃。 不知是不是产后抑郁。看着自己肥胖体型、变形的胸部,还有爱哭闹的孩子、躺在沙发上玩手机的老公。我...

  • 奔溃

    午夜十二点到家 一点的时候整理好准备休息 二点左右后面那家的那老头还在骂人 五点左右他家已经起床了,貌似在剥笋 六...

  • 奔溃

    现在正是我和女儿最难的时候,她有自己的思想,而且自我为中心。希望大家围着她转。常常说:我就要……我就想……会埋怨大...

网友评论

      本文标题:valueForKeyPath 奔溃

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