Swift内存管理:在var中存储func [英] Swift Memory Management: Storing func in var

查看:65
本文介绍了Swift内存管理:在var中存储func的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm looking for the best practice for storing functions as variable in other objects. Specifically, I'm looking to avoid retain cycles inherent in capturing self in the function.

来自Objective-c和代码块,我通常会这样做:

Coming from objective-c and blocks, I would normally do something like this:

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

当然,iVar类将复制该块并将其存储.因为我捕获了__weak id _self,所以没有保留周期.

Of course, the iVar class would copy the block and store it. No retain cycle exists because I've capture __weak id _self.

在Swift中,我不太确定,尤其是因为我可以传递类函数/方法.因此,假设我们在iVar类中:

In Swift, I'm a little less certain, especially since I can pass class functions/methods. So, let's say in the iVar class I have:

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

现在在主"类中,我具有上述类的实例变量,并且可以:

Now in my "main" class I have an instance variable of the above class and I do:

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

我们这里有保留周期吗?我会这样认为,也许我需要使callback较弱:

Do we have a retain cycle here? I would think so, and I think that perhaps I need to make the callback weak:

    weak var callBack:() -> ()?

当然,我可以在主类中做类似的事情:

Of course, I could do something like this in the main class:

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

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

But it's so nice to be able to pass class functions as arguments! Also, if I do need to make the callback weak, then I think I would loose the ability to assign it a closure (because after the assignment, the closure would be released from memory with only one weak reference).

另外,请注意,现在内存管理责任由接收者而不是分配者来承担,但是由于接收者不知道分配的来源,因此不能真正承担责任.换句话说,现在在接收者和分配者之间必须隐式地约定要传递什么样的功能,这是脆弱的,不建议使用.当分配者负责时,它可以采取步骤以确保没有保留周期,但是接收者则不能采取此类步骤.

Also, notice how the onus for memory management responsibility is on the receiver now instead of the assigner, but since the receiver cannot know the source of the assignment it can't really be held responsible. In other words, there must now be a implicit contract between the receiver and the assigner on what kind of function is to be passed, which is fragile and not-recommended. When the assigner is responsible, it can take steps to ensure there's no retain cycle, but the receiver cannot take such steps.

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

This makes me think that we should never pass a class function to another object. It's too dangerous. You can't know how the receiver will store/use it.

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

Or am I missing something? Does Swift magically resolve this problem behind the scenes?

@Kirsteins指出了我遗忘的一些内容:捕获列表.因此,您无需在声明中显式声明weak var _self = self,而是可以在闭包中声明它:

@Kirsteins pointed out something I'd forgotten about: capture lists. So instead of explicitly declaring weak var _self = self, You can declare it in the closure instead:

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

这是更好的方法,但不如简单地分配类函数那么优雅.

This is better, but not so nearly as elegant as simply assigning the class function.

我想我想让Swift将类函数自动转换为带有捕获列表的闭包,所以我不必这样做.公平地说,这并不完全困难,但是如果我可以分配类函数的话,当然会更漂亮.地狱,即使这样会更好:

I think what I want is for Swift to auto convert a class function into a closure with a capture list so I don't have to do it. To be fair, it's not exactly difficult, but certainly is a lot prettier if I could just assign the class function. Hell, even this would be nicer:

self.iVar.callback = weak self.doSomething

推荐答案

您不能做这样的事情:

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

据我了解,通过这种方式,您将不会直接捕获self,从而避免了保留周期.

It is my understanding that this way you wouldn't be capturing self directly and thus would avoid a retain cycle.

这篇关于Swift内存管理:在var中存储func的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆