swift - 如何在没有强引用循环的情况下将对象生命周期组合在一起?

标签 swift automatic-ref-counting

背景

我对 Swift 比较陌生(来自 C++ 和 C#)背景,并且正在努力解决如何最好地设计我的一些数据模型类型和接口(interface)。 ARC 看起来很棒,并且使某些事情变得更容易,但我发现自己遇到了某些设计挑战。

问题

假设我们想要用不同对象(A、B 和 C 类)的混合来表示一些复杂的、互连的数据。例如,假设每个 A 对象应该有一个关联的 B 对象和多个 C 对象。 A 对象还必须响应其链接对象的更改(例如,当 C 对象更改时,关联的 A 必须更新其自身的内部状态并通知其 B)。

由于 ARC,我们不能简单地让这些对象都相互强引用,否则我们最终会出现强引用循环(和内存泄漏)。

幸运的是,Swift 为我们提供了无主引用,因此我们总是可以像这样设置我们的关系(虚线是弱引用 ):

Object relationships

这是可行的,但设置起来可能有点麻烦,特别是对于大量互连的对象。如果我们使用第三方类(只能通过扩展来修改)那就更麻烦了。

此外,如果主 A 对象仅使用弱引用,它实际上无法自行保持关联的 B 或 C 对象处于事件状态。

反转我们的引用的方向将解决该特定问题,但它也带来了自己的缺点。

例如,假设 View 或 Controller 只需要与 C 对象交互。但是,如果它仅维护对这些 C 对象的引用,并且这些 C 对象仅具有对支持 A 对象的弱引用,则 A 对象可能会被释放。这基本上强制客户端代码保留对 A 对象的引用,以防止它关心的 C 对象成为孤立对象。

一厢情愿的想法

理想情况下,我希望简单轻松地将这些对象的生命周期联系在一起,但不会产生内存泄漏。换句话说,我想创建一个 A 对象(然后它会创建自己关联的 B 和 C 对象)并让它们彼此保持事件状态,但前提是外部代码至少有一个引用到这些“捆绑”对象中的任何一个。

这在 Swift 中可能(并且实用)吗?

更多细节

我不确定细节是否会澄清或使事情变得模糊,但如果它有帮助......我遇到的场景之一是建模数据并将其与核心数据一起存储。

例如,A是“公共(public)”程序员友好的接口(interface)(符合标准化数据协议(protocol)),B是“私有(private)”后备存储(核心数据实体),C是对复杂数据的有用封装。

还有一些我遗漏的相关 D 和 E 类,它们也与主 A 对象相关。这些本身很像我们这里的 A 类,即。数据模型的公共(public)接口(interface),具有自己复杂的多对象关系,但从根本上讲与我们的 A 到 C 关系存在相同的问题。

换句话说,客户端代码可能只需要与 D 交互,但单独修改 D 将无法正常工作,除非关联的 A 对象也以某种方式保持事件状态。

有点切线

这让我想知道核心数据实体如何在不引入强引用循环的情况下管理它们的关系。例如,您可能有 X、Y 和 Z 实体,它们都相互关联并相互依赖。

根据自动生成的类,我没有看到任何弱引用。这些托管对象如何维护彼此的引用而不发生内存泄漏?

最佳答案

我发现您可以使用两种可能的策略(可能还有其他策略):

1)拥抱强引用循环并明确拆除它

2) 通过使各个类能够根据需要动态实例化其引用的对象,使各个类变得自治。

对于#1,您可以要求调用代码调用一些“清理”方法来破坏强引用(例如,将强引用设置为 nil 的 A、B、C ... 类的方法) 。或者,您可以创建一个容器类来实例化对象并保存强引用,然后让调用代码拥有该容器。

对于#2,各个类只需要一个分层的强-><-弱关系,“子”对象将根据需要延迟地重新实例化它们的“父”实例(类似于 ManagedObjects 上的 CoreData 错误)。

关于swift - 如何在没有强引用循环的情况下将对象生命周期组合在一起?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46672526/

相关文章:

ios - 如何在 Swift 3 中解析巨大的 JSON 文件?

xcode - 在 xcode 中移动文件时出错

ios - 如何在用户完成在文本字段中输入数据后立即执行操作?

objective-c - Swift 与 ARC 之前的 Objective-C 不兼容吗?

iphone - 为什么这段代码会给我一个关于弱属性的错误?

ios - 在启用 ARC 的情况下将强引用对象设置为 nil?

ios - UIScrollView 将内容推离页面

ios - 自定义 UITableViewCell 图像上的圆角

objective-c - 为什么 ARC 禁止调用未声明的方法?

ios - init方法中的弧导致内存泄漏