Swift内存管理:在var中存储func

时间:2015-01-23 14:31:15

标签: swift memory-management retain-cycle

我正在寻找将函数存储为其他对象变量的最佳实践。具体来说,我希望避免在函数中捕获self时固有的保留周期。

来自objective-c和blocks,我通常会这样做:

__weak id _self = self;
iVar.someBlock = ^{
    [_self doSomething];
};

当然,iVar类会复制块并存储它。没有保留周期,因为我捕获了__weak id _self

在Swift中,我不太确定,特别是因为我可以传递类函数/方法。所以,我想在iVar课程中说:

class iVarClass {
    var callBack:() -> ()?
    func jumpUpAndDown(){
        //Weeeeeee!
        self.callBack?()
    }
}

现在在我的“main”类中,我有一个上面类的实例变量,我这样做:

class mainClass {
    var iVar: iVarClass
    init(iVar:iVarClass){
        self.iVar = iVar
        iVar.callback = self.doSomething
    }
    func doSomething(){
      self.iVar.jumpUpAndDown?()
    }
}

我们这里有保留周期吗?我会这么认为,我想也许我需要让callback弱:

    weak var callBack:() -> ()?

当然,我可以在主要课程中做这样的事情:

    init(iVar:iVarClass){
        self.iVar = iVar
        weak var _self = self
        iVar.callback = {
            _self?.doSomething()
        }
    }

但能够将类函数作为参数传递真是太好了!另外,如果我确实需要使callback弱,那么我认为我将失去为它分配一个闭包的能力(因为在赋值之后,闭包将从只有一个弱引用的内存中释放)。

另外,请注意内存管理责任的责任现在是如何在接收方而不是分配方,但由于接收方无法知道分配的来源,因此无法真正承担责任。换句话说,接收者和分配者之间必须有一个隐含的契约,要求传递什么样的功能,这是脆弱的而不是推荐的。当分配者负责时,可以采取措施确保没有保留周期,但接收者不能采取这些步骤。

这让我觉得我们应该从不将类函数传递给另一个对象。这太危险了。您无法知道接收器将如何存储/使用它。

或者我错过了什么?斯威夫特在幕后神奇地解决了这个问题吗?

更新

@Kirsteins指出了我忘记的事情:捕获列表。因此,不是明确声明weak var _self = self,而是可以在闭包中声明它:

    init(iVar:iVarClass){
        self.iVar = iVar
        iVar.callback = { [weak self] in
            self?.doSomething()
        }
    }

这更好,但不如简单地分配类函数那么优雅。

我认为我想要的是让Swift自动将类函数转换为带有捕获列表的闭包,所以我不必这样做。公平地说,这并不是很难,但如果我可以分配类函数,肯定会更漂亮。天哪,即使这样会更好:

self.iVar.callback = weak self.doSomething

1 个答案:

答案 0 :(得分:0)

你做不到这样的事情:

class mainClass {
    var iVar: iVarClass
    init(iVar:iVarClass){
        self.iVar = iVar
        func go() {
            self.doSomething()
        }
        iVar.callback = go
    }
    func doSomething(){
      self.iVar.jumpUpAndDown?()
    }
}

我的理解是,通过这种方式,您不会直接捕获self,从而避免保留周期。