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

内部闭包的捕获列表是否需要将“ self”重新声明为“ weak”或“ unowned”?

袁鸿畅
2023-03-14
问题内容

如果我有一个闭包传递给这样的函数:

 someFunctionWithTrailingClosure { [weak self] in
     anotherFunctionWithTrailingClosure { [weak self] in 
         self?.doSomething()
     }
 }

如果我[weak self]someFunctionWithTrailingClosure的捕获列表中声明self为,而没有weak在的捕获列表中再次声明自身,则它anotherFunctionWithTrailingClosure
self已经成为一种Optional类型,但它也同样成为weak引用吗?

谢谢!


问题答案:

[weak self]anotherFunctionWithTrailingClosure是没有必要的。

您可以凭经验进行测试:

class Experiment {

    func someFunctionWithTrailingClosure(closure: () -> ()) {
        print("starting someFunctionWithTrailingClosure")
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(1 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) {
            closure()
            print("finishing someFunctionWithTrailingClosure")
        }
    }

    func anotherFunctionWithTrailingClosure(closure: () -> ()) {
        print("starting anotherFunctionWithTrailingClosure")
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(1 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) {
            closure()
            print("finishing anotherFunctionWithTrailingClosure")
        }
    }

    func doSomething() {
        print("doSomething")
    }

    func testCompletionHandlers() {
        someFunctionWithTrailingClosure { [weak self] in
            self?.anotherFunctionWithTrailingClosure { // [weak self] in
                self?.doSomething()
            }
        }
    }

    // go ahead and add `deinit`, so I can see when this is deallocated

    deinit {
        print("deinit")
    }
}

然后:

func performExperiment() {
    dispatch_async(dispatch_get_global_queue(QOS_CLASS_UTILITY, 0)) { 
        let obj = Experiment()

        obj.testCompletionHandlers()

        // sleep long enough for `anotherFunctionWithTrailingClosure` to start, but not yet call its completion handler

        NSThread.sleepForTimeInterval(1.5) 
    }
}

如果执行此操作,您将看到doSomething永不被调用,并且deinitanotherFunctionWithTrailingClosure调用其闭包之前被调用。

验证了此行为后,我个人仍然倾向于使用[weak self]语法anotherFunctionWithTrailingClosure使我的意图明确,因为所有这些远非显而易见。



 类似资料:
  • 问题内容: 在我经历1000 s 之后,可能不需要 是否有 任何情况下, 该下降从将使在差异 封装 (或 使用 例如,通过外)?还考虑思考 如果 不 建议将其删除或使其与编码风格保持一致? 我说 没有 和 下降 ,但不知道真的。 编辑: 刚意识到 我 的方式肯定是错误的-至少对于的 字段 -声明这些字段为私有字段,然后在外部类中使用它们- 因为这会在字节码中生成( “ synthetic” )访问

  • 我已经签出了答案,比如变量是在内部类中访问的。需要被宣布为最终,但它没有解决我想要的。 我正在使用GraphView绘制从Google Firebase检索到的数据。数据应该是如下所示的连续线: 但当我运行程序时,它却是这样进行的: 我应该做些什么来解决这个问题?任何形式的帮助都将不胜感激。谢谢!

  • 我正在尝试创建一个布局为“是”或“否”的警报对话框。我想通过单击“否”按钮而不是对话框视图来关闭该对话框。Disclose() 有错误。 这是我的密码。

  • 我得到了一个问题,对内部类的局部变量访问需要声明为final。从方法createGrids()->“”中,i是一个需要声明为final的局部变量。我不知道为什么,我在字段中添加了final,但它并不起作用。 //略

  • 问题内容: 有必要避免内存泄漏吗? 问题答案: 不,在这种情况下不需要。并且不会被保留,因此没有强大的保留周期的风险。

  • 问题内容: 尝试在内部类内部使用一个类的本地成员时遇到此错误。我知道将其声明为final将解决此问题,但我读到Java 8应该自动处理它,因为我将Intellij与Java 8一起使用,但它仍然无法编译。还有其他方法可以在不将其声明为final的情况下进行修复吗?谢谢。 问题答案: 我知道将其声明为final将解决此问题,但我读到Java 8应该自动处理它。 如果变量 有效地为final ,则Ja