在转换为NSString后释放CFStringRef

ndg*_*ndg 5 memory cocoa memory-leaks objective-c

我正在转换一个Objective-C函数,它将CFStringRef转换为类似的NSString(其中FSEventStreamCopyDescription返回一个CFStringRef):

return (NSString *)FSEventStreamCopyDescription(eventStream);
Run Code Online (Sandbox Code Playgroud)

但是,在分析我的应用程序时,我被告知由于缺少CFRelease调用,这将导致"潜在泄漏".我正在尝试重写此函数以避免任何泄漏.处理这个问题的正确方法是什么?我提供了两种可能性(两者都可能不正确):

选项A:

CFStringRef ref = FSEventStreamCopyDescription(eventStream);
NSString *desc = [(NSString *)ref copy];
CFRelease(ref);

return [desc autorelease];
Run Code Online (Sandbox Code Playgroud)

选项B:

CFStringRef ref = FSEventStreamCopyDescription(eventStream);
NSString *desc = [[NSString alloc] initWithString:(NSString *)ref];
CFRelease(ref);

return [desc autorelease];
Run Code Online (Sandbox Code Playgroud)

Pet*_*sey 5

Casting对该对象没有任何作用.演员只会告诉编译器"这真的是一个_____".

它对内存管理规则也没有任何作用.您仍然拥有一个从遵循CF规则并在其名称中包含Copy的函数中获取的对象.因此,你拥有那个对象; 因此,你有责任释放它.

重要的不是班级的名称; 免费桥接意味着CFString NSString.重要的是规则从下面得到对象的函数或方法(CF规则基础规则),以及是否遵守它们.

选项A和B都解决了问题,但复杂性过高.

选项A中的复制和发布无效.你已经复制了它; 制作另一份副本不会改变这种情况.它只会浪费你的时间和用户的时间.

选项B 的initWithString:(或stringWithString:)也没有实现.您已经有一个CFString,而CFString是一个NSString,因此您不需要创建NSString.最终,这相当于选项A.

@ kubi的回答是迄今为止最好的,但有一个改进:

return [NSMakeCollectable(FSEventStreamCopyDescription(eventStream)) autorelease];
Run Code Online (Sandbox Code Playgroud)

通过此更改,代码将在垃圾收集下正常工作,autorelease无需执行任何操作.同时,根据保留/释放规则,NSMakeCollectable什么都不做.无论哪种方式,您的所有权将在适当的时间发布/收集.