当前位置: 首页 > 面试题库 >

快速闭合导致自我强烈的保留周期

盖绪
2023-03-14
问题内容

我只是想知道我是否正确理解了这一点。因此,根据苹果公司的文档,当您将闭包作为类实例的属性创建并且闭包引用self(创建闭包属性的类)时,这将导致强大的保留周期,最终该类或闭包都不会被释放。因此,用外行术语来说,这意味着如果我有一个具有属性的类并且该属性是一个闭包,并且一旦我在html" target="_blank">声明闭包属性的类中分配了该闭包的功能,就会导致强烈的保留周期。这是我的意思的简单例子

class SomeViewController{
  let myClosure:()->Void

  public func someFunction(){
    ....bunch of code
    myClosure = {
       self.dismiss(blahBlahBlah)
    }
  }
}

这最终导致了一个保留周期,因为闭包一直强烈引用self,这是创建闭包属性的类。现在要根据苹果解决此问题,我将定义一个捕获列表,如下所示

class SomeViewController{
  let myClosure:()->Void

  public func someFunction(){
    ....bunch of code
    myClosure = { [weak self] in
       self?.dismiss(blahBlahBlah)
    }
  }
}

注意我如何将[弱自我]放在in语句之前。这使闭包知道仅持有对自身的弱引用而不是强引用。IM应该在自己可以生存的情况下使用弱势,或者在关闭和自我生存的时间相同时不使用IM。

我从“
自动引用计数”和该链接的
“强引用闭环” 部分中获得了此信息,这句话是: “如果将闭包分配给类实例的属性以及主体的主体,也会出现强引用环该关闭捕获了该实例”,
我大约90%的人确信我正确理解了这一点,但只有10%的疑问。那我有这个正确吗?

我问这个的原因是因为我在视图中对某些按钮使用了回调。这些回调调用了self,但是在这种情况下,self是响应回调的视图控制器,而不是实际的视图本身。这是我怀疑自己的地方,因为我从那句话中强调了我,我认为我不需要进行[weak self]所有这些按钮回调,而只是确定一下。这是一个例子

class SomeViewController {
    let someSubview:UIView

    override viewDidLoad() {
       //Some Subview has a button and in that view I just have some action that gets fired off calling the callback here in the view controller I don't need to use the [weak self] in this scenario because closure property is not in this class correct?
       someSubview.someButtonsCallback = {
       ....run code then 
       self?.dismiss(blahBlahBlah)
     }
 }

问题答案:

是的,那仍然会导致保留周期。

最简单的保留周期是2个对象,每个对象相互之间都有很强的引用,但是3向和更大的保留周期也是可能的。

在您的情况下,您的视图控制器的视图包含一个按钮(强引用)。该按钮具有对闭包的强引用。闭包使用self强烈引用视图控制器。因此,视图拥有该按钮。该按钮拥有闭包。该闭包拥有视图控制器。如果您关闭视图控制器(例如它是模式控制器),则应该将其释放。但是,由于您具有此3向保留周期,因此不会取消分配它。您应该使用打印语句将deinit方法添加到视图控制器,然后尝试使用它。

解决方案[weak self]像在第一个示例中那样添加捕获列表(该位)。

请注意,常见的模式是添加捕获列表,然后将弱变量映射到闭包内部的强变量:

let myClosure = { [weak self] in 
  guard let strongSelf = self else { return }
  //...
  strongSelf.doSomething()
}

这样,如果闭包仍处于活动状态,但拥有它的对象已被释放,则开始时的guard语句会检测到self为nil,并在闭包的开头退出。否则,每次引用可选项时都必须将其拆开。

在某些情况下,捕获列表中的对象(在这些示例中为self)也有可能被释放到正在执行的闭包的中间,这可能导致无法预测的行为。(详细信息:仅当闭包在与捕获列表中对象的所有者不同的线程上运行时,但完成处理程序通常在后台线程上运行,因此确实发生)

想象一下:

let myClosure = { [weak self] in

  self?.step1() //1

  //time-consuming code

  self?.property = newValue //2

  //more time-consuming code

  self?.doSomething() //3

  //even more time-consuming code

  self?.doSomethingElse() //4
}

使用上面的代码,如果闭包在后台线程上运行,则可能在第1步中self仍然有效,但是到您执行第2步时,self已被释放。步骤3和步骤4也是如此。通过guard strongSelf = self else { return }在闭包的开头添加,您可以在闭包的入口处进行测试以确保self仍然有效,如果是,则使闭包创建一个仅能生存的强引用。只要闭包需要运行,并且可以防止self在执行闭包代码时将其释放。)



 类似资料:
  • 问题内容: 使用Jackson将hibernate对象转换为JSON时,我遇到问题,因为某些对象在其定义中具有自引用。问题是我无法控制这些实体的代码,因此无法在其中放置注释。 实际上,我只想将递归的深度限制为例如5个级别。我需要与包含自我引用的任何实体对象一起使用的通用代码。可能吗?我不介意使用另一个JSON库。 下面的简单代码 给我例外: 在此先感谢您的任何建议! 问题答案: 使用Jackson

  • 最有力的色彩组合是充满刺激的快感和支配的 欲念,但总离不开红色;不管颜色是怎么组合,红 色绝对是少不了的。红色是最终力量来源——强烈、大胆、极端。 力量的色彩组合象征人类最激烈的感情:爱、恨、 情、仇,表现情感的充分发泄。 在广告和展示的时候,有力色彩组合是用来传 达活力、醒目等强烈的讯息,并且总能吸引众人的 目光。 补色色彩组合 原色色彩组合 单色色彩组合 55 7 52 4 68 36 4 7

  • 问题内容: 使用Jackson将休眠对象转换为JSON时,我遇到了问题,因为某些对象在其定义中具有自引用。问题是我无法控制这些实体的代码,因此无法在其中放置注释。 实际上,我只想将递归的深度限制为例如5个级别。我需要与包含自我引用的任何实体对象一起工作的通用代码。可能吗?我不介意使用另一个JSON库。 下面的简单代码 给我例外: 在此先感谢您的任何建议! 问题答案: 使用Jackson 2.0-

  • 问题内容: 我下面有一个简单的课程 我在这里初始化 但是,这导致xcode打印出200 5s,然后由于EXC_BAD_ACCESS code = 2而崩溃。为什么会发生这种情况? 问题答案: @vadian在他的回答中提供了一个解决方案,它可以解决您的问题。让我解释一下发生了什么。 您已经创建了一个计算属性,即一个没有变量支持的属性,取而代之的是,getter和setter方法通常在另一个存储的属

  • 编译器错误,这是有意义的,因为它将在函数返回后调用。 但如果我将闭包设置为可选的,那么没有编译器错误,这是为什么?在函数返回后仍然可以调用闭包。

  • 本文向大家介绍快速关闭android studio的自动保存功能教程,包括了快速关闭android studio的自动保存功能教程的使用技巧和注意事项,需要的朋友参考一下 1、进入设置:File > Settings。 2、去掉红框两处勾选。 Save files on frame deactivation Save files automatically if application is id