在编译时块会发生什么,我可以在运行时创建一个块吗?

时间:2013-05-01 17:22:38

标签: objective-c objective-c-blocks introspection

这是关于 Objective-C blocks (^ {})的两部分问题。我已经搜索了一些答案,但没有任何内容出现在Google或SO中。这个问题源于为iOS创建自定义XML Layout Engine的愿望,支持块 - 这意味着我想解析NSStrings并在运行时创建一个块。

1)这甚至可能吗?如果是这样,怎么办呢?

NSString to Block上找不到多少,我认为原因可能是编译器如何处理一个块 - 所以我再次搜索一个答案但空手而归。所以:

2)在Objective-C编译时块发生了什么?

3 个答案:

答案 0 :(得分:5)

一个块是两件事;执行经过块时捕获的一大块可执行代码和状态。

即。给出:

 myBlock = ^{ return someVariable + someOtherVariable; };

编译时,这会创建一个代码块,其行为非常类似于将两个变量一起添加的函数返回结果。没有创建块实例。

执行时,在计算表达式myBlock = ^{...};时,会创建一个块实例。在该块实例内部是对编译器创建的代码的引用,以及在分配给myBlock时两个变量中包含的值的副本(当然,除非__block正在播放,等等......)。

答案(2),但与回答(1)有关。

在运行时,您可以整天创建现有的,已编译的块的实例。但是,您无法创建新的块。这样做需要编译器,并且仅限于编译新的可执行代码并实际执行它的运行时环境。

答案 1 :(得分:0)

您不能轻易做的是在运行时编译Objective-C代码以创建块。你可以做的是为你的布局DSL创建一个小解析器并创建一个块树。例如,可以使用嵌套块实现数学表达式解析器。

以下是表达式“2 + 3 * 4”的示例:

typedef double(^MathBlock)(void);

MathBlock exprL = ^(void) { return 3.0; };
MathBlock exprR = ^(void) { return 4.0; };

exprR = ^(void) { return exprL() * exprR();  };
exprL = ^(void) { return 2.0; };

exprR = ^(void) { return exprL() + exprR();  };

double result = exprR();

显然,您需要编写解析函数来解释XML以返回这些块。使用递归下降解析器时,这一点特别简单。

答案 2 :(得分:0)

1)如果你的意思是在运行时编译一个块,没有。编译器在运行时不可用。 2)显然,在编译时编译一个块。它是运行时的可执行代码,如函数或方法或其中任何一部分。但是块的编译方式可以发送给后执行和处理块变量魔术。