块定义之间的iOS循环依赖关系

时间:2012-10-16 16:12:55

标签: ios typedef objective-c-blocks block

在我的iOS应用程序中,我想定义两个以彼此为参数的块类型:

typedef void (^BlockA)(BlockB b);
typedef void (^BlockB)(BlockA a);

在第一个typedef中使用'未知类型名称BlockB'编译失败(这是有意义的)。

我有一个解决方法,它定义了这样的类型:

typedef void (^BlockA)(id);
typedef void (^BlockB)(BlockA a);

然后我回到BlockA定义中的BlockB类型,但代价是安全性。

我还考虑过不使用typedef,但这会导致扩展块定义的无限嵌套。

我知道如何使用前向声明来解析结构的循环依赖关系,但是我看不到如何使用块来执行此操作。

如果没有循环依赖的解决方案,有没有办法可以将BlockA的参数限制为任何Block类型而不是通用id,这将提供某种级别的类型安全性。< / p>

1 个答案:

答案 0 :(得分:2)

typedef未定义&#34;真实&#34;类型。它基本上就像一个宏,它扩展到它所使用的任何地方。这就是为什么typedef不能递归的原因。

考虑它的另一种方法是,typedef s永远不是必需的 - 你总是可以使用typedef来获取任何代码,并简单地用基础类型替换它的每一个代码(这是编译器在编译时所做的事情),它将始终有效并且完全等效。想一想 - 没有typedef你会怎么做?你不能。因此,您无法使用typedef进行此操作。

唯一的方法是:使用id作为参数类型来删除你正在做的类型;或者,将块封装在&#34; real&#34;类似于struct或类。但是,如果以后一种方式执行此操作,则必须将块显式放入并从结构或类中提取块,这会使代码混乱。此外,struct是危险的,因为struct是标量C类型,如果您需要通过块捕获它,它不会自动内存管理结构内的对象。至于类,定义一个包装类非常冗长,并且使用它会导致为它包装的每个块分配一个无关的虚拟对象。

在我看来,像你一样使用id使用很好,是最干净的方式。但是,请记住,如果您需要将该块传递为id被另一个内部块捕获,则应该在捕获之前将其强制转换为块类型,因为块的捕获语义不同其他对象类型(复制块,而保留其他对象)。只需在最早的地方将其重新放回块类型即可。