何时使用takeUnretainedValue()或takeRetainedValue()来检索Swift中的非托管对象?

时间:2015-03-14 12:18:45

标签: ios objective-c iphone swift

根据Using Swift with Cocoa and Objective-C,您可以使用takeUnretainedValue()takeRetainedValue()告诉Swift如何管理对象的内存,如下所示:

func StringByAddingTwoStrings(CFString!, CFString!) -> Unmanaged<CFString>!

我何时必须使用takeUnretainedValue()takeRetainedValue()

当我使用ARC时,它总是takeUnretainedValue()

2 个答案:

答案 0 :(得分:53)

当非托管对象具有+1保留计数并且您希望ARC在完成后负责释放对象时,使用takeRetainedValue。例如,如果您使用名称中的CreateCopy调用Core Foundation函数(请参阅适用于Core Foundation的内存管理编程指南中的Create Rule),返回一个您负责释放的非托管对象,通常使用takeRetainedValue以便它为您释放(或者,如果您不这样做,则必须使用{{1}自行手动释放它或类似的功能)。当对象的所有权尚未转移给您时,您使用CFRelease,因此当您的对象超出范围时,您不希望ARC为您释放该对象。

因此,关于何时调用takeUnretainedValue vs takeUnretainedValue,它只取决于被调用函数返回的对象类型。作为一般经验法则,如果对象是从名称中带有takeRetainedValueCreate的Core Foundation函数返回的,请使用Copy。否则使用takeRetainedValue


如果您调用错误的方法会发生什么,如果您在传递+1对象时调用takeUnretainedValue(例如,使用takeUnretainedValue或{{从Core Foundation函数返回的对象1}}在名称中),除非您明确Create,否则您的应用会泄露。运行应用程序时,您可能不会立即注意到偶然的泄漏,但可以通过观察应用程序的内存使用情况来观察(例如,如果您使用仪器分析您的应用程序)。但如果您将这些泄漏未解决,您的应用程序最终可能会收到内存警告。

另一方面,如果你在一个尚未为你保留的对象上调用Copy(由名称中没有CFReleasetakeRetainedValue的函数返回,当对象被释放时,应用程序可能会崩溃。有时这不会立即显现(直到最后一个强引用被解决),但它通常会导致应用程序的灾难性故障。

明智地选择Create vs Copy非常重要。

答案 1 :(得分:0)

从NSHipster报价:

https://nshipster.com/unmanaged/

  

非托管实例包装了CoreFoundation类型T,只要非托管实例本身在范围内,就保留对基础对象的引用。有两种方法可以从非托管实例中获取Swift托管的值:

     
      
  • takeRetainedValue()返回对包装实例的Swift管理的引用,并在执行此操作时减少引用计数-与Create Rule函数的返回值一起使用。

  •   
  • takeUnretainedValue()返回对包装实例的Swift管理的引用,而不减少引用计数-与Get Rule函数的返回值一起使用。

    < / li>