优化捕获列表

问题描述 投票:4回答:2

有这样的事吗?下面两个有什么区别吗?一个比另一个更“正确”吗?

所有对象都是self的属性(比如一个视图控制器)并且与self具有相同的生命周期。我们可以引入一个寿命比self更短的物体,它将是weak,但同样的问题也适用。

objectOne.doSomething { [unowned self] in
    self.objectTwo.finish()
    self.tableView.reloadData()
    // self.someDelegate?.didFinishSomething()
}

VS

objectOne.doSomething { 
    [unowned objectTwo = self.objectTwo,
    unowned tableView = self.tableView
    // weak someDelegate = self.delegate
    ] in
    objectTwo.finish()
    tableView.reloadData()
    // someDelegate?.didFinishSomething()
}

Apple在their docs中有这个例子:

lazy var someClosure: () -> String = {
    [unowned self, weak delegate = self.delegate!] in
    // closure body goes here

    delegate?.doSomething()
}

在这种情况下,delegate的寿命可能比self短,但为什么不这样使用呢?

lazy var someClosure: () -> String = { 
    [unowned self] in
    // closure body goes here

    self.delegate?.doSomething()
}
ios swift memory-management closures
2个回答
1
投票

是的,有一个重要的区别。对于Apple文档,您提供的代码替代方案:

lazy var someClosure: () -> String = { 
    [unowned self] in
    // closure body goes here

    self.delegate?.doSomething()
}

当关闭运行时,将在delegate上查找当前的self

在Apple示例版本中:

lazy var someClosure: () -> String = {
    [unowned self, weak delegate = self.delegate!] in
    // closure body goes here

    delegate?.doSomething()
}

捕获列表中的弱delegate var正在复制delegate上的self指针,该指针存在于闭包声明时,而不是执行。因此,如果self.delegate的值在声明闭包后发生变化,并且在闭包运行时不同,那么闭包的Apple版本将具有nil委托(假设因为对旧委托的引用很弱)并且什么都不做。

因此,作为一般规则,在捕获列表([someIdentifier = someProperty])中复制值或引用是如何使用在定义闭包时存在的值或引用。而在捕获列表([weak self])中声明弱或无主自我然后访问该弱引用({ self?.someProperty })上的属性将获得执行闭包时存在的属性值。


0
投票

[unowned objectOne = self.objectOne]可能导致的问题之一是lazy var UIViews和竞争条件:如果你不小心并且从不同的线程调用lazy init,最终可能会创建两个实例。此外,如果您的superview.addSubview(objectOne)调用位于lazy init中,则两个实例都将添加到superview中,而objectOne将指向两个实例中的一个。

© www.soinside.com 2019 - 2024. All rights reserved.