我应该削弱"本地"块中使用的变量?

时间:2018-04-27 10:28:22

标签: ios swift

这不是关于[weak self]的另一个问题。这是关于使用self未包含的变量,而是使用包装函数。

func someFunction(){
    someOtherFunction(completionBlock:{ [weak self] in
        self?.doStuff()
    })
}

据我了解,我需要[weak self]才能阻止保留周期。

但是,如果我需要使用包装函数中的变量,如下所示:

func someFunction(){
    let someVariable = MyObject()
    someOtherFunction(completionBlock:{ [weak self] in
        self?.doStuff(with: someVariable)
    })
}

这有效,这让我很奇怪.. someVariable在记忆中的持续时间和持续时间有多长?它可以创建自己的小保留周期,我的完成块强烈引用本地someVariable吗?它们将如何发布? 应该我在块中添加[weak self, weak someVariable]吗?但是,在我致电someVariable后立即释放someOtherFunction,因为它是此功能的结束 - 以及someVariable'一生......?

我无法完全理解参考文献,也无法看到我的completionBlocksomeVariable将如何发布..块是否已被释放?

2 个答案:

答案 0 :(得分:4)

闭包内引用的任何变量都将被该闭包强烈保留。您可以通过包含闭包捕获列表(例如[weak self])来调整它,这允许您指定闭包中捕获的引用的特定内存管理模式。

func someFunction(){
    let someVariable = MyObject()
    someOtherFunction(completionBlock:{ [weak self] in
        self?.doStuff(with: someVariable)
    })
}

正如您所说,此处,闭包保留someVariable。在这种情况下,它,因为没有其他人关心它。正如您在评论中提到的那样,如果您使用了[weak someVariable]的捕获列表,那么在执行完成块时它总是为零,因为它已经超出了它的原始功能范围。

A"微小的保留周期"没有被创造。保留周期必须是周期 - 也就是说,A保存对B的强引用,B具有对A的强引用。someVariable没有引用任何内容。

一旦someOtherFunction完成对完成闭包的引用,一切都会消失。就someOtherFunction而言,闭包只是另一个变量,只要它在范围内,它就会存活下来。

我应该弱化块中使用的“局部”变量吗? - 不,因为它们在块使用它们时将为零。

答案 1 :(得分:0)

我想提一下不那么明确的选项,创建保留周期的常用位置是什么,以及应该注意弱化变量的地方。

让我们考虑一下这种情况:

func someFunction() {
    let object = Something()
    object.handler = { [weak self] in 
       self?.doStuff(with: object)
    }
}

现在有保留周期,并且在有人手动取消设置object之前,handler无法取消分配。因为现在对象在捕获的块中强化自身。

更好的解决方案是:

func someFunction() {
    let object = Something()
    object.handler = { [weak self, unowned object] in 
       self?.doStuff(with: object)
    }
}

好的做法是在object

中传递handler作为参数
func someFunction() {
    let object = Something()
    object.handler = { [weak self] (object) in 
       self?.doStuff(with: object)
    }
}

所以签名应该是这样的:

class Something {
    var handler:((Something) -> Void)?
    deinit {
        print("retain cycle is not here")
    }
}