如何为闭包分配内存&它的存储机制是什么?

时间:2016-08-25 15:18:01

标签: ios swift closures

我想深入了解闭包及其分配和使用机制。在阅读并使用它们一段时间后,我想出了一些真正让我头疼的问题:

问题 - 1 从内存分配的角度来看,闭包如何用作与正常变量不同的变量?

例如:let x:NSString ={}()& let x = NSString()

问题-2 块的内存分配究竟如何?

请妥善解释这些,以便任何有类似疑虑的读者都可能从中受益。

**编辑* Shadow提出的这个问题的答案是针对这个问题的另一个方向进行了编辑。

1 个答案:

答案 0 :(得分:1)

对于具有默认值或默认闭包的存储属性,在调用init方法之前,内存会分配。您不能使用self或属性来默认值定义其他属性。

通常在此步骤中使用的示例中的闭包来定义lazy属性;它们应为var并标有lazy关键字:

class myClass {
    let x: NSString? = nil
    let q: NSString? = {return "q"}() //allocates before class init; deallocates imidiatly
    lazy var y: NSString = {
        let z  = self.x
        return z ?? ""
    }()                               //allocates on first property call; deallocates imidiatly
}

延迟属性的内存将在第一次属性调用时分配。构造{/*...*/}()意味着此闭包将在调用时执行,并将返回计算结果(您可以在未命名的函数中查看它),而不是引用此闭包。这是非常重要的时刻:你没有保留闭包,这个闭包只分配执行时刻并在返回后释放,所以你不需要关心强循环引用问题。

其他事项 - 当您保存对闭包的引用时:

class myClass {
    let x: NSString? = nil
    var closure: () -> NSString = {return "q"} //allocates before class init; deallocates on references release
    lazy var lazyClosure: () -> NSString = {
        let z  = self.x
        return z ?? ""
    }                                        //allocates on first property call; deallocates on references release
}

此闭包的内存与之前的情况同时分配,但它们将继续存在,直到有任何引用。你可以在这里查看闭包,就像在不同的对象一样。这里可能出现循环参考问题。 closure没有捕获任何内容,因此它没有任何问题,但lazyClosure捕获self。如果我们永远不会调用lazyClosure那么就没有问题,因为这个闭包永远不会分配。但是,如果我们将其调用,它将被分配,它将捕获self,并且将有强循环引用:self指向lazyClosure实例,lazyClosure指向self个实例。要解决此问题,您应该使其中一个引用变弱,您应该使用捕获列表:在[weak self] in正文中插入[unowned self] inlazyClosure。我们的情况为[unowned self] in,因为如果调用了属性,则self不是nil

lazy var lazyClosure: () -> NSString = {
    [unowned self] in
    let z  = self.x
    return z ?? ""
}