【问题标题】:Do I need to manually release CFStringRef?我需要手动释放 CFStringRef 吗?
【发布时间】:2026-02-09 23:45:01
【问题描述】:

您能否告诉我在非 ARC 世界中哪种方法是正确的以及为什么。

+ (NSString *)getUUID {
CFUUIDRef theUUID = CFUUIDCreate(NULL);
CFStringRef string = CFUUIDCreateString(NULL, theUUID);
CFRelease(theUUID);
return [(NSString*) string autorelease];
}

+ (NSString *)getUUID {
CFUUIDRef theUUID = CFUUIDCreate(NULL);
CFStringRef string = CFUUIDCreateString(NULL, theUUID);
CFRelease(theUUID);
return (NSString*)string;
}

【问题讨论】:

  • 我建议改用 NSUUID。
  • @Catfish_Man 我喜欢你的方式,但唯一的问题是 NSUUID 在 iOS 6 中被添加到 Foundation。我的应用目标是 iS 5.0。所以我必须 CFUUIDRef。

标签: ios objective-c memory-management core-foundation


【解决方案1】:

CFStrings 确实需要被释放。第一种方法是正确的,因为 CFString 是带有 NSString 的toll-free bridged,因此可以像 NSString 一样安全地自动释放。

【讨论】:

    【解决方案2】:

    您的方法应该返回一个自动释放的对象,以便客户端负责获得对该对象的所有权,并且如果他们忽略返回值,它就不会泄漏。

    第一个是正确的方法。 CFString 被创建,+1 保留计数,自动释放并返回给客户端。转换为NSString 不会影响保留计数。

    在第二种方法中,CFString 被创建,+1 保留计数,但从不与释放或自动释放平衡。

    【讨论】:

    • @Inafziger 总的来说我绝对同意,但是这篇文章使用了正确的相对“+1”表示法(= 由于“一个太多”的保留,保留计数不平衡)。跨度>
    • 称之为“引用计数”
    • @lnafziger 我用 +1 表示增量
    • @MatthiasBauch 每个人都知道我在说什么,这就是它在代码中所指的内容。在苹果框架的范围之外,我会
    • @lnafziger 我的意思是当我说“保留计数”而不是“引用计数”时,每个人都知道我在说什么
    【解决方案3】:

    其他答案对于手动保留计数是正确的。当您恢复理智 ;^) 并切换到 ARC 时,您将无法发送 autorelease。相反,在 ARC 下,这样做:

    + (NSString *)getUUID {
        CFUUIDRef theUUID = CFUUIDCreate(NULL);
        CFStringRef string = CFUUIDCreateString(NULL, theUUID);
        CFRelease(theUUID);
        return CFBridgingRelease(string);
    }
    

    为了平衡 CFUUIDCreateString 返回的 +1 保留计数,CFBridgingRelease 等效于 CFRelease,但还返回 ARC 将负责释放的仍然有效的引用。

    【讨论】:

    • 在 ARC 下(或真正在非 ARC 下),我会这样做: + (NSString *) UUID { return [[NSUUID UUID] UUIDString]; }
    • @Catfish_Man 我喜欢你的方式,但唯一的问题是 NSUUID 在 iOS 6 中被添加到 Foundation。我的应用目标是 iS 5.0。所以我必须 CFUUIDRef。
    • 我认为这是一个非 ARC 问题?这在 ARC 之外仍然有效吗?
    • 是的,这是一个非 ARC 问题。我添加了这个答案是为了让那些发现这个问题并使用 ARC 的人受益,因为标题和标签没有提到 ARC 或 MRC。我不知道为什么这被选为接受的答案。