Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 反思当前块上下文&xE0;方法中的la_cmd_Objective C_Objective C Blocks_Introspection_Objective C Runtime - Fatal编程技术网

Objective c 反思当前块上下文&xE0;方法中的la_cmd

Objective c 反思当前块上下文&xE0;方法中的la_cmd,objective-c,objective-c-blocks,introspection,objective-c-runtime,Objective C,Objective C Blocks,Introspection,Objective C Runtime,对我来说,Objective-C对周围环境的反应、描述和干扰能力就是它所处的位置。这从一个基本的层面开始,在任何一点上都可以毫不动摇地引用\u cmd,并获取当前的SEL。从那以后,你可以选择参与什么NSInvocation咒语或运行时诡计 现在,在一个块中,您仍然可以调用\u cmd,获得当前“上下文”的模糊描述,即 描述性的?对提供有用信息的可以但没那么有用。如何在块中获取动态和准确的运行时信息,特别是调用签名、参数等 这是一个很好的例子,说明了我希望在区块内收集的信息类型 typedef

对我来说,Objective-C对周围环境的反应、描述和干扰能力就是它所处的位置。这从一个基本的层面开始,在任何一点上都可以毫不动摇地引用
\u cmd
,并获取当前的
SEL
。从那以后,你可以选择参与什么
NSInvocation
咒语或运行时诡计

现在,在一个块中,您仍然可以调用
\u cmd
,获得当前“上下文”的模糊描述,即

描述性的?对提供有用信息的可以但没那么有用。如何在块中获取动态和准确的运行时信息,特别是调用签名、参数等

这是一个很好的例子,说明了我希望在区块内收集的信息类型

typedef void(^blockHead)(NSString*);
blockHead v = ^(NSString*sandy) {  NSLog(@"damnDog",nil); };
Log([v blockDescription]);

[v blockDescription] = <NSMethodSignature: 0x7fd6fabc44d0>
    number of arguments = 2
    frame size = 224
    is special struct return? NO
    return value: -------- -------- -------- --------
        type encoding (v) 'v'
        flags {}
        modifiers {}
        frame {offset = 0, offset adjust = 0, size = 0, size adjust = 0}
        memory {offset = 0, size = 0}
    argument 0: -------- -------- -------- --------
    type encoding (@) '@?'
    flags {isObject, isBlock}
    modifiers {}
    frame {offset = 0, offset adjust = 0, size = 8, size adjust = 0}
    memory {offset = 0, size = 8}
argument 1: -------- -------- -------- --------
    type encoding (@) '@"NSString"'
    flags {isObject}
    modifiers {}
    frame {offset = 8, offset adjust = 0, size = 8, size adjust = 0}
    memory {offset = 0, size = 8}
        class 'NSString'
typedef void(^blockHead)(NSString*);
区块头v=^(NSString*sandy){NSLog(@“damnDog”,nil);};
日志([v blockDescription]);
[v blockDescription]=
参数数量=2
框架尺寸=224
特殊结构是否返回?不
返回值:-------------------------------
类型编码(v)‘v’
标志{}
修饰语{}
帧{offset=0,offset adjust=0,size=0,size adjust=0}
内存{offset=0,size=0}
参数0:------------------------------
类型编码(@)@?“
标志{isObject,isBlock}
修饰语{}
帧{offset=0,offset adjust=0,size=8,size adjust=0}
内存{offset=0,size=8}
论据1:---------------------
类型编码(@)@“NSString”
标志{isObject}
修饰语{}
帧{offset=8,offset adjust=0,size=8,size adjust=0}
内存{offset=0,size=8}
类“NSString”

如果深入挖掘,确实可以使用某些特定于目标的程序集

您将在三种主要体系结构上运行objective-c代码,它们是:

  • x86:iOS模拟器和古老的Mac
  • x86_64:Mac OSX
  • ARM:iOS设备
通过使用lldb调试器以及大量的黑客攻击,我找到了用于每个平台的寄存器(用于保存块指针):

  • x86:
    ecx
    /
    edi
  • x86_64:
    rcx
    /
    rdi
  • ARM:
    r0
    /
    r4
在所有平台上,值似乎位于两个单独的寄存器中,一个来自调用点,另一个来自传递的参数

利用这些信息,我制作了几个宏,这些宏将与GCC和Clang一起工作,以将所述寄存器的值转换为C变量:

#if TARGET_CPU_X86_64 
// OSX, the block pointer is in the register 'rcx'.
// The 'mov' instruction does not clobber the register,
// So we can simply (ab)use that here.
#define BLOCK_GET_SELF() ({ id __block_self_tmp; __asm__("mov %%rcx, %0" : "=r"(__block_self_tmp)); __block_self_tmp; })
#elif TARGET_CPU_X86 
// iOS Simulator, the block pointer is in the register 'ecx'.
// Same deal as with x86_64 code, except it's in a 32-bit register.
#define BLOCK_GET_SELF() ({ id __block_self_tmp; __asm__("mov %%ecx, %0" : "=r"(__block_self_tmp)); __block_self_tmp; })
#elif TARGET_CPU_ARM64
// iOS Device, ARM64 (iPhone 5S, iPad Mini 2, iPad Air).
// The block pointer is in the x0 register, and the x4 register.
// Similar code to the TARGET_CPU_ARM function.
#define BLOCK_GET_SELF() ({ id __block_self_tmp; __asm__("str x0, [%0]" :: "r"(&__block_self_tmp)); __block_self_tmp; })
#elif TARGET_CPU_ARM 
// iOS Device, the block pointer is in register 'r0'.
// The 'mov' (move) instruction clobbers the r0 register
// (which messes up the debugger) for whatever reason,
// so we use the 'str' (store) instruction instead.
#define BLOCK_GET_SELF() ({ id __block_self_tmp; __asm__("str r0, [%0]" :: "r"(&__block_self_tmp)); __block_self_tmp; })
#endif

void blockTest() {
    __block void *blockPtr = NULL;
    void (^myBlock)() = ^{
        id this = BLOCK_GET_SELF();

        printf("this is:\t\t0x%.8lx\n", (uintptr_t) this);
        printf("blockPtr is:\t0x%.8lx\n", (uintptr_t) blockPtr);
    };

    // example using dispatch
    blockPtr = (__bridge void *) myBlock;
    dispatch_async(dispatch_get_main_queue(), myBlock);
}
输出,运行iOS 7 Beta 2的iPhone 5:

this is: 0x17e7c890 blockPtr is: 0x17e7c890 这是:0x17e7c890 块PTR为:0x17e7c890
请随时让我知道这个代码的任何问题,我希望它能帮助你

除非您能够以某种方式引用它,否则您无法真正了解块内部的块本身。顺便说一句,为什么你想知道这些信息?随着块API的激增。。通常很难告诉打电话的人街区等。。编译器允许不匹配的签名。。。参数数量不正确,且有多个方法,名称相同,但块类型不同,等等=共存而无投诉。。。有时候,如果能知道实际发生了什么,那就太好了。。。不仅仅是“我认为”发生了什么。你可以在调用它之前检查块的类型,但是你不能在块内部做很多事情,因为它可能已经被错误的参数调用了。正如你所看到的,在第一个参数a la
self
中,块确实传递了自己,但是你的代码中不存在该参数的名称。没有办法参考它。我认为你能做的最好的事情就是对每个块调用进行某种包装。“现在,在一个块内..你仍然可以调用_cmd并获得当前“上下文”的模糊描述。例如,uu 30-[RoomController awakeFromNib]u Block_uinvoke123RoomController“不,你不能”。这不是来自
\u cmd
。 this is: 0x17e7c890 blockPtr is: 0x17e7c890