Tom*_*Tom 12 cocoa objective-c automatic-ref-counting
我曾经像这样将NSError强制转换为CFErrorRef并在SMJobBless中使用它
NSError *error
BOOL removed = SMJobRemove(kSMDomainSystemLaunchd,
(CFStringRef) daemonBundleID,
auth,
true,
(CFErrorRef*) &error);
if (!removed) {
NSLog(@"Failed to remove existing PacketTool");
[NSApp presentError: error];
}
Run Code Online (Sandbox Code Playgroud)
由于我在ARC中遇到错误,"ARC禁止使用指向'CFErrorRef'的Obj-C指针的间接指针",我改变并决定做相反的事情
CFErrorRef *cfError = nil;
BOOL blessed = SMJobBless(kSMDomainSystemLaunchd, (__bridge CFStringRef)daemonBundleID,
auth,
cfError);
if (!blessed) {
NSError *error = (__bridge NSError *)cfError;
NSLog(@"Failed to bless PacketTool: %@", error);
[NSApp presentError: error];
return FALSE;
}
Run Code Online (Sandbox Code Playgroud)
现在我有一个"不兼容的类型转换'CFErrorRef'到NSError*"与__bridge强制转换
我能做什么?
更新:感谢Greg,正确的代码现在是:
CFErrorRef cfError = nil;
BOOL blessed = SMJobBless(kSMDomainSystemLaunchd,
(__bridge CFStringRef) daemonBundleID,
auth,
&cfError);
if (!blessed) {
NSError *error = (__bridge NSError *)cfError;
NSLog(@"Failed to bless PacketTool: %@", error);
[NSApp presentError: error];
return FALSE;
}
Run Code Online (Sandbox Code Playgroud)
Gre*_*reg 21
当你声明cfError时你不应该使用指针*,你应该使用:
CFErrorRef cfError = nil;
NSError *error = (__bridge NSError *)cfError;
Run Code Online (Sandbox Code Playgroud)
在另一种方式,它的工作方式如下:
NSError *error = nil;
CFErrorRef ref = (__bridge CFErrorRef) error;
Run Code Online (Sandbox Code Playgroud)
希望这有帮助.
Mec*_*cki 10
在2013年12月7日16:05,汤姆补充说:
更新:感谢Greg,正确的代码现在是:
Run Code Online (Sandbox Code Playgroud)CFErrorRef cfError = nil; BOOL blessed = SMJobBless(kSMDomainSystemLaunchd, (__bridge CFStringRef) daemonBundleID, auth, &cfError); if (!blessed) { NSError *error = (__bridge NSError *)cfError; NSLog(@"Failed to bless PacketTool: %@", error); [NSApp presentError: error]; return FALSE; }
我知道这篇文章已经有2年了,但它错了,我不希望其他程序员复制错误的代码.此代码泄漏内存,因为CFError永远不会释放!
CoreFoundation没有自动内存管理,在使用ARC时也没有.ARC仅适用于Obj-C对象.和的CoreFoundation不知道自动释放或自动释放池,这样的CoreFoundation对象(CFStringRef,CFNumberRef,CFErrorRef等),你的CoreFoundation功能得到永远不会自动释放.它们要么根本不需要释放,要么由它来释放它们.如果出现错误(CFErrorRef *),则由您来释放它们.
代码的第一部分是正确的:
CFErrorRef cfError = nil;
BOOL blessed = SMJobBless(
kSMDomainSystemLaunchd,
(__bridge CFStringRef)daemonBundleID,
auth, &cfError
);
Run Code Online (Sandbox Code Playgroud)
但是你需要了解桥梁铸造.最简单的形式或桥梁铸造只是__bridge这个演员告诉ARC"不要做任何事情".如果你这样做
NSError * error = (__bridge NSError *)cfError;
Run Code Online (Sandbox Code Playgroud)
你告诉ARC:"铸cfError到error ,但投后不管理错误的记忆,这不关你的事. "
如果你这样做,你仍然有责任释放CFErrorRef!这意味着一旦你完成cfError 和使用error("和"因为两者都指向同一个对象,如果它被销毁,两个指针都变得无效),你必须这样做:
CFRelease(cfError);
Run Code Online (Sandbox Code Playgroud)
否则你是在泄漏记忆!
或者,你可以告诉ARC为你管理内存,但是你需要一个不同的演员阵容.如果你这样投
NSError * error = (__bridge_transfer NSError *)cfError;
Run Code Online (Sandbox Code Playgroud)
你告诉ARC:"投cfError给error 然后将其由你来管理的记忆error. "
现在您不需要发布任何内容,因为只要error超出范围,ARC就会为您发布.而且因为error并且cfError实际上是同一个对象,释放error也是释放cfError,所以现在你不需要发布任何东西.顾名思义,此转换将对象"转移"到ARC.一旦完成,你就不cfError能再使用,因为你无法确定ARC何时会释放error,并且一旦它确实cfError是一个无效的指针,使用它可能会轻易崩溃你的整个应用程序.
如果你向另一个方向投掷也是如此.如果你这样做
NSError * error = ...;
CFErrorRef cfError = (__bridge CFErrorRef)error;
Run Code Online (Sandbox Code Playgroud)
ARC仍将管理内存error,这是危险的,如上所述,当ARC决定它可以销毁时error,cfError也会变得无效.如果您只cfError在当前范围内使用,这是可以的,但如果您的CFErrorRef需求不管ARC做什么,那么您可以执行此操作:
NSError * error = ...;
CFErrorRef cfError = (__bridge_retained CFErrorRef)error;
Run Code Online (Sandbox Code Playgroud)
这告诉ARC:" 保留error一次,然后施放error,cfError 并且不要平衡这个初始保留. "
因此,即使error超出范围,ARC也不会释放它,因为对象的保留计数器不会变为0,因为该转换,它仍然至少为1.现在由您来处理内存管理,这意味着一旦完成cfError,您必须释放它:
CFRelease(cfError);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5284 次 |
| 最近记录: |