【问题标题】:Swift How to return child object that keeps parent object as long as child lives in memorySwift如何返回只要子对象存在于内存中就保留父对象的子对象
【发布时间】:2020-09-21 16:40:14
【问题描述】:

我考虑是否可以从在父对象中创建的函数子对象返回,该子对象将保留对其父对象的引用并防止父对象从内存中释放。同时我不想保留循环和内存泄漏。

class ObjectA { 
   let objectB = ObjectB()
}

class ObjectB { 

}

func factoryFunc() -> ObjectB { 
   ObjectA().objectB
}

客户端代码

let objB = factoryFunc() 
// but keep also ObjectA as long as objB lives 
// but do not create retain cycle
// I do not want to return ObjectA and do not want to manage it outside of black box factory method. 

我可以添加

class ObjectB { 
    var parent: ObjectA?
}

它会产生保留周期和内存泄漏

class ObjectB { 
        weak var parent: ObjectA?
    }

这不会阻止 ObjectA 的释放

【问题讨论】:

  • ObjectA 必须持有对 ObjectB 的引用吗?
  • 我认为是的,因为实际上它是具有 objectB 作为 rootViewController 的流控制器,因此 objectB 用于推送新控制器。我可以返回这个 flowController 但它只在应用程序之一的情况下才有意义。在使用它的其他应用程序中,我更喜欢直接返回 rootViewController 但仍然重用这个 flowcontroller 导航。
  • 你能在所谓的父 ObjectA 中使 ObjectB 引用“弱”吗?
  • 如果是流程问题,您确实可以在viewWillDisappear 或其他一些我们称之为flowcycle 方法中创建强引用并处理内存清理。
  • 我可以创建保留周期,然后在 viewWillDisappear 中打破它,就像将 nil 分配给 var parentObjA: ObjectA 一样。嗯,这是个好主意。但最后我创建了同时包含 ObjectA 和 ObjectB 的 ObjectC。 C是NavigationController,它持有FlowController并将它的rootViewController用作NavigationController的rootViewController

标签: swift memory-leaks factory weak-references retain-cycle


【解决方案1】:

除了创建一个强引用循环之外别无他法。但是,如果您达到了这一点,则设计中可能存在问题;您永远不需要创建强大的参考循环。在你的情况下:

  1. 也许你不应该直接使用ObjectB,而是通过ObjectA的一些设计接口。

  2. 如果你只需要ObjectB,那么你就不需要ObjectA

  3. 如果ObjectA 在您的应用程序中如此重要,那么您应该在该工厂之外对其进行管理。

如果您不需要使用ObjectA(因为您不希望它返回),并且您不会在该范围之外管理它,那么您当然根本不需要它,您将能够将您的逻辑移到该类之外(或者可能继承ObjB 中的ObjA)。

如果您仍然需要以其他隐藏方式使用它,那么您应该创建某种控制器或管理器来管理您使用类的整个流程。

另外,非常重要的是,请记住,所有权必须只有一种方式,而不能同时使用两种方式,而且控制流几乎总是与所有权相同。如果ObjectAObjectB 的父级,那么ObjectB 应该对ObjectA 一无所知。

【讨论】:

  • ObjectA 是子 FlowController,ObjectB 是 rootViewController。 FlowController 管理 ObjectB 的这部分应用子视图的导航。所以流量很重要。但另一方面,我不想返回整个 FlowController,而只是返回 rootViewController,但在这个 flowController 中保留导航逻辑。也许我应该包装 ViewController 或 NavigationController 引用流控制器并将这个 rootViewController 添加为其根
  • 这种情况下的流控制器应该是某种单例并且应该管理根视图控制器。您应该能够从任何地方访问流控制器,然后流控制器应该负责创建根视图控制器。尝试将层次结构保持在您的依赖关系中。另一种方法是交换所有权,这意味着根视图控制器有一个流控制器并询问它应该如何管理流。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-31
相关资源
最近更新 更多