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

con*_*ile 32 iphone objective-c ios swift

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

func StringByAddingTwoStrings(CFString!, CFString!) -> Unmanaged<CFString>!
Run Code Online (Sandbox Code Playgroud)

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

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

Rob*_*Rob 57

您可以使用takeRetainedValue在非托管对象有一个+1保留计数,你想ARC采取释放对象时,即可大功告成的照顾.例如,如果您使用CreateCopy在名称中调用Core Foundation函数(请参阅Core Foundation内存管理编程指南中的创建规则),该函数返回您负责释放的非托管对象,通常使用它以便它被释放对于你(或者,如果你不这样做,你必须自己手动释放它或类似的功能).您在对象的所有权尚未转移给您时使用,因此您不希望ARC在超出范围时为您释放该对象.takeRetainedValueCFReleasetakeUnretainedValue

因此,至于何时调用takeUnretainedValuevs takeRetainedValue,它只取决于被调用函数返回的对象类型.作为一般经验法则,如果对象是使用名称CreateCopy名称从Core Foundation函数返回的,请使用takeRetainedValue.否则使用takeUnretainedValue.


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

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

所以明智地选择takeUnretainedValuevs takeRetainedValue非常重要.

  • @confile如果在传递保留对象时调用`takeUnretainedValue`,您的应用程序将泄漏.您可能不会注意到除了您的应用程序之外的其他应用程序(如果您使用仪器,您可以看到),并且您最终可能会收到内存警告.如果你在调用未保留版本时调用`takeRetainedValue`,应用程序可能会崩溃(虽然不一定立即). (5认同)
  • @confile"我如何从API了解所有权是否已转移?" 惯例是,如果函数在名称中包含"Create"或"Copy",则所有权已被转移.如果没有,所有权尚未转移. (3认同)

pka*_*amb 5

引自 NSHipster:

https://nshipster.com/unmanaged/

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

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

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