7

我正在寻找将函数作为变量存储在其他对象中的最佳实践。具体来说,我希望避免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?()
    }
}

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

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弱化,那么我想我会失去为它分配闭包的能力(因为在分配之后,闭包将从内存中释放,只有一个弱引用)。

另外,请注意内存管理责任的责任现在是由接收者而不是分配者承担,但由于接收者不知道分配的来源,它不能真正负责。换句话说,现在接收者和分配者之间必须有一个关于要传递什么样的函数的隐式契约,这是脆弱的,不推荐使用。当分配者负责时,它可以采取措施确保没有保留周期,但接收者不能采取这样的措施。

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

还是我错过了什么?Swift 是否在幕后神奇地解决了这个问题?

更新

@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
4

1 回答 1

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,因此可以避免保留周期。

于 2015-12-21T18:24:46.070 回答