gpt4 book ai didi

ios - block 和消息

转载 作者:可可西里 更新时间:2023-11-01 06:19:38 25 4
gpt4 key购买 nike

这里的问题更像是一个教育问题。一个小时前我开始想到这个在乐高积木周围翻转(我知道这很傻)。

根据我的理解, block 是在堆栈上创建的对象。

假设 A 是一个对象,这意味着我们可以:

[A message];

基于此,如果一个 block 是一个对象,我们还可以这样做:

[block message];

我说的对吗?

当运行时看到它时,它会调用:

objc_msgSend(block, @selector(message), nil);

所以我的问题是,我们如何向 block 发送消息?

如果可能的话,我想也可以向 block 发送一条消息,其参数也是 block ?

并且,如果我们可以通过以下方式调用 block :

block();

这是否意味着我们甚至可以将 block 作为消息 (SEL),因为 block 具有类似于 void (^)(void) 的签名一种方法?

因为如果有可能,那么下面的内容会让我大吃一惊:

objc_msgSend(block, @selector(block), block);

或:

objc_msgSend(block1, @selector(block2), block3);

我希望我的想象力不会有点疯狂,并且我的理解不会偏离这里(如果是的话,请纠正我)。

最佳答案

block 是仅用于存储和引用目的的对象。通过使它们成为对象, block 可以被保留/释放,因此可以被放入数组或其他集合类中。他们还响应 copy

就是这样。即使是从堆栈开始的 block 在很大程度上也是编译器实现细节。

当一个 block 的代码被调用时,这不是通过 objc_msgSend() 完成的。如果您要阅读 block 运行时和 llvm 编译器的源代码,那么您会发现:

  • 一个 block 实际上是一个 C 结构,它包含对已捕获数据的描述(因此可以清理)和一个指向函数的指针——指向一段代码——也就是 block 的可执行部分

  • block 函数是标准 C 函数,其中第一个参数必须始终是对 block 的引用。参数列表的其余部分是任意的,就像任何旧的 C 函数或 Objective-C 方法一样工作。

因此,您对 objc_msgSend() 的手动调用会将 block 视为任何其他随机 ObjC 对象,因此不会调用 block 中的代码,如果调用了(并且有是可以通过方法执行此操作的 SPI...但是,不要使用它)它可以传递一个完全可控的参数列表吗?


除此之外,尽管相关。

imp_implementationWithBlock() 获取一个 block 引用并返回一个可以插入到 Objective-C 类中的 IMP(请参阅 class_addMethod()),这样当该方法是被调用时,该 block 被调用。

imp_implementationWithBlock() 的实现利用了 objective-c 方法与 block 调用站点的布局。 block 总是:

blockFunc(blockRef, ...)

ObjC 方法总是:

methodFunc(selfRef, SEL, ...)

因为我们希望 imp_implementationWithBlock() block 始终将目标对象作为第一个 block 参数(即 self)传递给方法,imp_implementationWithBlock() 返回一个蹦床函数,调用时(通过 objc_msgSend()):

- slides the self reference into the slot for the selector (i.e. arg 0 -> arg 1)
- finds the implementing block puts the pointer to that block into arg 0
- JMPs to the block's implementation pointer

找到实现 block 有点有趣,但与这个问题无关(该死,imp_implementationWithBlock() 也有点无关紧要,但可能很有趣)。


Thanks for response. It's definitely an eye opener. The part about blocks calling is not done thru objc_msgSend() tells me that it is because blocks are not part of the normal object-hierachry (but coda's mentioning of NSBlock seems to refute what I understand so far, because NSBlock would make it part of the object-hierachy). Feel free to take a stab at me, if my understanding is still off so far. I am very interested in hearing more about the followings 1: the SPI and the way (how) to call that method. 2: the underlying mechanisms of: sliding the self reference into the slot. 3: finds the implementing block and puts the pointer to that block into arg 0. If you have time to share and write a bit more about those in detail, I am all ears; I find this all very fascinating. Thanks very much in advance.

block 本身只是一个标准的 Objective-C 对象。 block 实例包含指向一些可执行代码的指针、任何捕获的状态,以及一些用于将所述状态从堆栈复制到堆(如果需要)并在 block 销毁时清除状态的助手。

block 的可执行代码不像方法那样被调用。 block 还有其他方法——retainreleasecopy 等等——可以像任何其他方法一样直接调用,但可执行代码不是公开的其中一种方法。

SPI 没有做任何特别的事情;它只适用于不带参数的 block ,它只不过是简单地执行 block()

如果你想知道整个参数幻灯片是如何工作的(以及它如何使尾调用通过 block ),我建议阅读 thisthis .此外, block 运行时、objc 运行时和 llvm 的源代码都可用。

这包括 IMP 捕获 block 并将其插入 arg0 的有趣部分。

关于ios - block 和消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22872822/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com