简体   繁体   English

Swift指示保留闭包参数

[英]Swift Indicate that a closure parameter is retained

Is there any way to indicate to a "client" of a specific method that a closure parameter is going to be retained? 有没有办法向特定方法的“客户端”指示将保留闭包参数?

For instance, having the following code: 例如,具有以下代码:

import Foundation

typealias MyClosureType = () -> Void

final class MyClass {

    private var myClosure: MyClosureType?

    func whatever(closure: MyClosureType?) {
        myClosure = closure
    }
}

Anyone could start using this class and passing closures to the method whatever without any idea about if it is actually being retained or not. 任何人都可以开始使用这个类,以及将封闭的方法whatever ,没有任何想法有关,如果它实际上是被保留与否。 Which is error prone and could lead to memory leaks. 哪个容易出错,可能导致内存泄漏。

For instance, a "client" doing something like this, would be never deallocated 例如,执行此类操作的“客户端”将永远不会被释放

final class MyDummyClient {

    let myInstance = MyClass()

    func setUp() {
        myInstance.whatever {
            self.whateverHandler()
        }
    }

    func whateverHandler() {
        print("Hey Jude, don't make it bad")
    }
}

That is why I would like to know if there is any way to prevent this type of errors. 这就是为什么我想知道是否有任何方法可以防止这种类型的错误。 Some type of paramater that I could add to the definition of my method whatever which gives a hint to the client about the need to weakify to avoid leaks 某些类型的参数,我可以添加到我的方法的定义, whatever哪个给客户提示需要弱化以避免泄漏

Whether the closure parameter is escaping or non-escaping is some indication to the caller whether it might be retained. 闭包参数是转义还是非转义是调用者是否可以保留的一些指示。 In particular, a non -escaping closure param cannot be retained by a function call. 特别是,函数调用不能保留转义闭包参数。

Per SE-0103 , non-escaping closures (currently marked @noescape ) will become the default in Swift 3, and you'll have to write @escaping if you want to save the closure, so situations like this will become a little more obvious. 根据SE-0103 ,非转义闭包(当前标记为@noescape )将成为Swift 3中的默认值,如果要保存闭包,则必须编写@escaping ,这样的情况会变得更加明显。

Otherwise, there is no language feature to help you here . 否则, 没有语言功能可以帮助您 You'll have to solve this problem with API design and documentation. 您必须使用API​​设计和文档解决此问题。 If it's something like a handler, I'd recommend a property, obj.handler = { ... } , or a method like obj.setHandler({ ... }) or obj.addHandler({ ... }) . 如果它类似于处理程序,我建议使用属性obj.handler = { ... }obj.setHandler({ ... })obj.addHandler({ ... }) That way, when reading the code, you can easily tell that the closure is being saved because of the = or set or add . 这样,在阅读代码时,您可以轻松地告知由于=setadd而保存了闭包。

(In fact, when compiling Obj-C, Clang explicitly looks for methods named set...: or add...: when determining whether to warn the user about retain cycles. It's possible a similar diagnostic could be added to the Swift compiler in the future.) (事实上​​,在编译Obj-C时,Clang在确定是否警告用户有关保留周期时显式查找名为set...:add...:方法 。可能会在Swift编译器中添加类似的诊断在将来。)

With the specific case you're presenting the closure itself is the only thing that will be retained, so if you correctly add [weak self] to your closure when you call it there shouldn't be any issues. 对于特定情况,你提出的闭包本身是唯一可以保留的,所以如果你在调用时正确地将[弱自我]添加到你的闭包中,那么应该没有任何问题。

I'm not sure what issue you're trying to protect against, but you might also thing about using delegation (protocols) rather than a closure. 我不确定你试图防范什么问题,但你也可能关于使用委托(协议)而不是闭包。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM