gpt4 book ai didi

block 定义之间的 iOS 循环依赖

转载 作者:可可西里 更新时间:2023-11-01 05:56:57 24 4
gpt4 key购买 nike

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

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

由于“第一个 typedef 中的未知类型名称 BlockB”(这是有道理的)编译失败。

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

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

然后我转换回 BlockA 定义中的 BlockB 类型,但以类型安全为代价。

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

我知道如何解决具有前向声明的结构的循环依赖性,但我不知道如何使用 block 来解决这个问题。

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

最佳答案

typedef 没有定义“真正的”类型。它基本上就像一个宏,可以在使用它的任何地方扩展。这就是 typedef 不能递归的原因。

另一种思考方式是,typedef 从来都不是必需的——您始终可以使用 typedef 获取任何代码片段,并简单地替换每次出现的它与底层类型(这是编译器在编译时所做的),并且它将始终有效并且完全等效。想一想——如果没有 typedef,您会怎么做?你不能。所以你也不能用 typedef 来做。

唯一的方法是:使用 id 作为参数类型来像你正在做的那样删除类型;或者,将 block 封装在“真实”类型中,例如 struct 或类。但是,如果采用后一种方式,则必须显式地将 block 放入结构或类中并将 block 从结构或类中提取出来,这会使代码变得困惑。此外,struct 很危险,因为 struct 是标量 C 类型,如果您需要通过 block 捕获它,它不会自动对结构内的对象进行内存管理。至于类,定义包装类非常冗长,为此使用它会导致为它包装的每个 block 分配一个无关的虚拟对象。

在我看来,像您正在使用的那样使用 id 很好,而且是最简洁的方法。但是,请记住,如果您需要让该 block 作为 id 被另一个内部 block 捕获,您应该在捕获之前将其转换回 block 类型,因为捕获语义是不同的对于 block 和其他对象类型(复制 block ,而保留其他对象)。只需将其转换回最早位置的 block 类型即可。

关于 block 定义之间的 iOS 循环依赖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12919010/

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