翻过乐高积木(傻,我知道).
根据我的理解,块是在堆栈上创建的对象.
假设A是一个对象,这意味着我们可以做到:
[A message];
基于此,如果块是一个对象,我们也可以这样做:
[block message];
我对么?
当运行时看到它时,它会调用:
objc_msgSend(block,@selector(message),nil);
所以我的问题是,我们如何发送一个消息块?
如果这是可能的,我会想象也可以发送一个块参数为块的消息?
并且,如果我们可以通过执行以下 *** 作来调用块:
block();
这是否意味着我们甚至可以将一个块作为消息(SEL),因为块具有类似于方法的签名voID(^)(voID)?
因为如果有可能,那么下面的内容会让我感到惊讶:
objc_msgSend(block,@selector(block),block);
要么:
objc_msgSend(block1,@selector(block2),block3);
我希望我的想象力不会有点疯狂,我的理解不在这里(如果是的话,请纠正我).
解决方法 块是仅用于存储和引用的对象.通过使它们成为对象,可以保留/释放块,因此可以将块推入数组或其他集合类中.他们也回复副本.就是这样.即使在堆栈上启动的块也主要是编译器实现细节.
调用块的代码时,不是通过objc_msgSend()完成的.如果您要阅读块运行时和llvm编译器的源代码,那么您会发现:
>一个块实际上是一个C结构,它包含已捕获数据的描述(因此可以清理)和指向函数的指针 – 一块代码 – 这是块的可执行部分
>块函数是标准C函数,其中第一个参数必须始终是对块的引用.参数列表的其余部分是任意的,就像任何旧的C函数或Objective-C方法一样.
因此,您对objc_msgSend()的手动调用会像任何其他随机ObjC对象一样处理该块,因此不会调用块中的代码,也不会调用它(如果有的话)(并且SPI可以通过方法执行此 *** 作). ..但是,不要使用它)它可以传递一个完全可控的参数列表.
一方面,虽然相关.
imp_implementationWithBlock()接受一个块引用并返回一个可插入Objective-C类的IMP(请参阅class_addMethod()),以便在调用该方法时调用该块.
imp_implementationWithBlock()的实现利用了objective-c方法与块的调用站点的布局.一块总是:
blockFunc(blockRef,...)
ObjC方法总是:
methodFunc(selfRef,SEL,...)
因为我们希望imp_implementationWithBlock()块始终将目标对象作为第一个块参数(即self)作为方法,imp_implementationWithBlock()返回一个trampoline函数,该函数在调用时(通过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
发现实现块位有点有趣,但与这个问题无关(地狱,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.
这些块本身就是一个标准的Objective-C对象.块实例包含指向某些可执行代码的指针,任何捕获的状态,以及用于将所述状态从堆栈复制到堆(如果请求)并清除块破坏状态的一些帮助程序.
块的可执行代码不像方法那样被调用.一个块有其他方法 – 保留,释放,复制等 – 可以像任何其他方法一样直接调用,但可执行代码不是公开的那些方法之一.
SPI没有做任何特别的事情;它只适用于不带参数的块,它只不过是简单地执行block().
如果你想知道整个参数幻灯片是如何工作的(以及它如何使尾部调用到块),我建议阅读this或this.同样,块运行时,objc运行时和llvm的源代码也是如此.都可以.
这包括IMP抓住块并将其推入arg0的有趣位.
总结以上是内存溢出为你收集整理的ios – 阻止和消息传递全部内容,希望文章能够帮你解决ios – 阻止和消息传递所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)