zoukankan      html  css  js  c++  java
  • ios NSMethodSignature and NSInvocation 消息转发

    1.首先获取消息转发时连个函数内部具体内容 MARK:这里是拿[@"xxxxx" length]调用拿来举例说明

    (lldb) po signature
    <NSMethodSignature: 0x170076f80>
        number of arguments = 2
        frame size = 224
        is special struct return? NO
        return value: -------- -------- -------- --------
            type encoding (Q) 'Q'
            flags {}
            modifiers {}
            frame {offset = 0, offset adjust = 0, size = 8, size adjust = 0}
            memory {offset = 0, size = 8}
        argument 0: -------- -------- -------- --------
            type encoding (@) '@'
            flags {isObject}
            modifiers {}
            frame {offset = 0, offset adjust = 0, size = 8, size adjust = 0}
            memory {offset = 0, size = 8}
        argument 1: -------- -------- -------- --------
            type encoding (:) ':'
            flags {}
            modifiers {}
            frame {offset = 8, offset adjust = 0, size = 8, size adjust = 0}
            memory {offset = 0, size = 8}
    (lldb) po anInvocation
    <NSInvocation: 0x178075d80>
    return value: {Q} 0
    target: {@} 0x17801e350
    selector: {:} length

    apple doc : https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html

    讲解type encoding具体用法:http://nshipster.com/type-encodings/

    2. 具体案例:json解析数据时 NSJSONSerialization 会自动把他们换成 NSNull。当我们再去用dict[@“hello”]的时候,就会出触发exception,导致程序崩溃(ios6会出现)

    两种实现:

    第一种:
    #import "NSNull+OVNatural.h" 
     
    @implementation NSNull (OVNatural) 
    - (void)forwardInvocation:(NSInvocation *)invocation 
    { 
        if ([self respondsToSelector:[invocation selector]]) { 
            [invocation invokeWithTarget:self]; 
        } 
    } 
     
    - (NSMethodSignature *)methodSignatureForSelector:(SEL)selector 
    { 
        NSMethodSignature *sig = [[NSNull class] instanceMethodSignatureForSelector:selector]; 
        if(sig == nil) { 
            sig = [NSMethodSignature signatureWithObjCTypes:"@^v^c"]; 
        } 
        return sig; 
    } 
     
    @end 
    第二种:
    #define NSNullObjects @[@"",@0,@{},@[]] 
     
    @interface NSNull (InternalNullExtention) 
    @end 
     
    @implementation NSNull (InternalNullExtention) 
     
    - (NSMethodSignature*)methodSignatureForSelector:(SEL)selector 
    { 
        NSMethodSignature* signature = [super methodSignatureForSelector:selector]; 
        if (!signature) { 
            for (NSObject *object in NSNullObjects) { 
                signature = [object methodSignatureForSelector:selector]; 
                if (signature) { 
                    break; 
                } 
            } 
     
        } 
        return signature; 
    } 
     
    - (void)forwardInvocation:(NSInvocation *)anInvocation 
    { 
        SEL aSelector = [anInvocation selector]; 
     
        for (NSObject *object in NSNullObjects) { 
            if ([object respondsToSelector:aSelector]) { 
                [anInvocation invokeWithTarget:object]; 
                return; 
            } 
        } 
     
        [self doesNotRecognizeSelector:aSelector]; 
    } 
    @end 
    - (void)forwardInvocation:(NSInvocation *)anInvocation  只需改变调用目标,使消息在新目标上得以调用即可。然而这样实现出来的方法与“备援接收者”方案所实现的方法等效,所以很少有人采用这么简单的实现方式。比较有用的实现方式为:在触发消息前,先以某种方式改变消息内容,比如追加另外一个参数。

    实现此方法时,若发现某调用操作不应由本类处理,则需调用超类的同名方法。这样的话,继承体系中的每个类都有机会处理此调用请求,直至NSObject。如果最后调用了NSObject类的方法,那么该方法还会继而调用“doesNotRecognizeSelector:”以抛出异常,此异常表明选择子最终未能得到处理。

    未完,待续....

  • 相关阅读:
    Python测试开发Tkinter-----(Button--按钮)
    Python测试开发Tkinter------(Frame--框架)
    Python测试开发Tkinter-----(Tkinter--创建顶层窗口及Label)
    python2.7 Scripts环境变量配置 requests bs4 selenium安装方法
    重要知识点:内网系列
    重点知识:系统区分法,响应码,client-ip限制,抓https包的方法
    重点知识:MD5
    01渗透测试基础
    渗透测试之信息收集篇
    sqlmap安装与使用基础
  • 原文地址:https://www.cnblogs.com/tinkl/p/3696651.html
Copyright © 2011-2022 走看看