“自我”在封闭中指的是什么 - 斯威夫特

时间:2016-03-26 16:05:46

标签: swift

我很难理解Swift中关闭中真正发生的事情,并希望有人能帮助我理解。

class MyClass {

    func printWhatever(words: String) {
        print(words)
    }

    func doWhatever() {
         dispatch_async(...) {   
              //why self      
              self.printWhatever("Hello")
        }
    }
}

self.printWhatever("Hello")行,为什么我必须使用selfxCode总是告诉我必须这样做,但我不确定为什么。所以,我的问题是闭包中究竟存储了什么。我知道一个闭包捕获周围的上下文。但是多少钱?是否捕获了MyClass的实例?

3 个答案:

答案 0 :(得分:3)

这是一个清晰的问题。只要您使用没有显式收件人的方法或属性名称,就会隐式将其发送到self。但是在匿名函数中,你必须明确这个事实。如果你要说

printWhatever("Hello")

...您可能没有意识到您隐含地捕获self。所以你可能没有意识到,如果这个匿名函数在self的某个地方itself to be stored,你可以结束一个可怕的保留周期。因此,编译器强制您明确地说出self ,以便您了解自己行为的含义。

这方面的证据是,在某些情况下,必须在匿名函数中说self。考虑一下:

func printWhatever(words: String) {
    print(words)
}

func doThis(f:()->()) {
    f()
}

func doWhatever() {
    doThis {
        self.printWhatever("Hello") // self is required
    }
}

在上面,必须self,因为编译器无法保证可能不会发生保留周期。但是现在看看如果我们添加@noescape属性会发生什么:

func printWhatever(words: String) {
    print(words)
}

func doThis(@noescape f:()->()) { // *
    f()
}

func doWhatever() {
    doThis {
        printWhatever("Hello") // ok!
    }
}

@noescape属性保证传递的函数将立即执行而不存储。因此不再需要self,因为不会发生保留周期。

就个人而言,我总是在任何我被允许的地方说self。我建议你这样做。

注意:语言更改proposalrejected,拒绝的理由之一就是我给出的一个:

  

在潜在转出的闭包中使用self.的要求是保留周期潜力的有用指标

答案 1 :(得分:1)

是否捕获了MyClass的实例?

答案 2 :(得分:1)

需要

self来捕获要发送消息的对象的实例。没有它,编译器不知道发送消息的人。 注意有时将self放入clojure会导致引用循环,基本上捕获的对象永远不会被释放,在这种情况下你应该在clojure中创建一个捕获列表并指定一个不同的内存管理,如{{ 1}}或unowned