回到使用ARC的Objective-C,这是不安全的:
MyClass* someObject = ...
__weak MyClass* weakSomeObject = someObject;
doSomething(^{
[weakSomeObject someMethod];
});
为什么?因为简单地调用方法不会导致ARC保留对象,因此someObject
实例可能会在执行someMethod
的过程中被释放和释放
将此转化为快速,它转换如下:
let someObject: MyClass = ...
doSomething { [weak someObject]
someObject?.someMethod()
}
?.
operator in swift regarding ARC, and is it safe to use with weak reference method calls?我可以想象swift编译器将上面的代码翻译成这样的代码:
let someObject: MyClass = ...
doSomething { [weak someObject]
if let tmp = someObject {
tmp.someMethod()
}
}
如果它这样做,那么它确实是安全的,因为tmp
是一个强大的参考,因此会导致ARC在调用someMethod
的整个过程中保留对象
但是,我还可以想象,由于性能原因或其他原因,它会转换成没有ARC保留的东西。
有谁知道它实际上做了什么,是否有一个规范或文件使这个明确?
要获得第一个要点:
现在关于?
。它是可选的链接,如果调用哪个方法的对象是nil,它将不会调用方法以及完整链失败(如果您使用另一个方法调用跟踪返回值,否则)。
关于weak
和unowned
引用封闭内的已使用对象:
weak
没有创建对象的强引用,所以它使它成为可选的,因为当它被调用时对象可能不存在unowned
以及weak
不会创建强引用,但是对象不是可选的,因此您必须保证闭包不会比它使用的对象寿命更长,因为您将获得崩溃引用不存在的对象。希望能帮助到你。
简短的回答是肯定的,这是安全的。更长的解释和链接如下:
为Swift中的类型定义的方法是curried函数,如下所示:
class MyClass {
func doSomething() {
// I can access self in here
}
}
print(type(of: MyClass.doSomething)) //(MyClass) -> () -> ()
换句话说,在类型上定义的函数是curry,因此必须首先传递对self
的引用,()->()
在返回的部分应用函数中强烈捕获(self
)
当你在MyClass的实例上调用方法时(不是类型本身),它会自动执行传入MyClass.doSomething
实例的初始部分应用程序,然后由实际调用的结果闭包强烈捕获。
所以(MyClass) -> () -> ()
的类型是MyClass().doSomething
,而() -> ()
的类型是() -> ()
,其中最初的MyClass参考已经被捕获在weak var test: MyClass? = MyClass()
test?.doSomething()
内。
鉴于以下代码:
test
在第2行,发生了一些事情。首先,如果(MyClass) -> () ->()
是非零的,它将被传递给MyClass类型的方法实现,并由MyClass类型的curried函数()->()
捕获。此捕获的引用是可以在该实例方法中使用的“self”。
然后,调用self
类型的结果部分应用函数,并且一旦函数执行,就释放来自上面的https://oleb.net/blog/2014/07/swift-instance-methods-curried-functions/的强引用/捕获。
因此,答案是肯定的,在弱引用上调用实例方法是安全的,因为实例方法实际上强大地捕获实例,直到它执行为止。
这篇文章讨论了如何更详细地描述Swift中的实例方法,以及指向信息的初始dev论坛源的链接。
http://rosslebeau.com/2016/sneaky-reference-cycles-swift-instance-methods
关于这种机制的一些其他有趣和深入的文章:
https://www.klundberg.com/blog/capturing-objects-weakly-in-instance-method-references-in-swift/
qazxswpoi