Objective c 使用圆弧将CFErrorRef投射到N错误(或相反)上
我曾经像这样对CFErrorRef抛出一个NSError,并在SMJobBless中使用它Objective c 使用圆弧将CFErrorRef投射到N错误(或相反)上,objective-c,cocoa,automatic-ref-counting,Objective C,Cocoa,Automatic Ref Counting,我曾经像这样对CFErrorRef抛出一个NSError,并在SMJobBless中使用它 NSError *error BOOL removed = SMJobRemove(kSMDomainSystemLaunchd, (CFStringRef) daemonBundleID, auth, true,
NSError *error
BOOL removed = SMJobRemove(kSMDomainSystemLaunchd,
(CFStringRef) daemonBundleID,
auth,
true,
(CFErrorRef*) &error);
if (!removed) {
NSLog(@"Failed to remove existing PacketTool");
[NSApp presentError: error];
}
由于我在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;
}
现在我有了一个“将'CFErrorRef'转换为NSError*的不兼容类型”和_桥转换
我能做什么
更新:感谢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;
}
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;
}
声明cfError时,不应使用指针*,应使用:
CFErrorRef cfError = nil;
NSError *error = (__bridge NSError *)cfError;
另一方面,它的工作原理如下:
NSError *error = nil;
CFErrorRef ref = (__bridge CFErrorRef) error;
希望能有所帮助。12月7日13日16:05,汤姆补充道: 更新:感谢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;
}
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;
}
我知道这篇文章已经两年了,但它是错误的,我不希望其他程序员复制错误的代码此代码泄漏内存,因为CFError从未释放强>
CoreFoundation没有自动内存管理,在使用ARC时也没有。圆弧仅适用于Obj-C对象。而且CoreFoundation不知道自动释放或自动释放池,因此从CoreFoundation函数获得的CoreFoundation对象(CFStringRef
,CFNumberRef
,CFErrorRef
等)永远不会自动释放。他们或者根本不需要被释放,或者由你来释放他们。如果出现out错误(CFErrorRef*
),则由您来释放它们
另见
代码的第一部分是正确的:
CFErrorRef cfError = nil;
BOOL blessed = SMJobBless(
kSMDomainSystemLaunchd,
(__bridge CFStringRef)daemonBundleID,
auth, &cfError
);
但你需要了解桥梁浇筑。最简单的桥型铸造就是\u桥型,该铸造告诉ARC“什么都不要做”。如果你这样做
NSError * error = (__bridge NSError *)cfError;
您告诉ARC:“将cfError
转换为error
,但不要在转换后管理错误记忆,这与您无关。”
如果您这样做,您仍有责任发布CFErrorRef
!这意味着,一旦使用cfError
和error
完成(“和”都指向同一个对象,如果这两个指针都被破坏,则两个指针都将无效),您必须执行以下操作:
CFRelease(cfError);
否则,您正在泄漏内存
或者,您可以告诉ARC为您管理内存,但您需要另一种类型。如果你像那样投
NSError * error = (__bridge_transfer NSError *)cfError;
您告诉ARC:“将cfError
转换为error
,然后由您管理error
的内存。”
现在,您不需要发布任何内容,因为只要error
超出范围,ARC就会为您发布它。因为error
和cfError
实际上是同一个对象,释放error
也会释放cfError
,所以现在不需要释放任何东西。顾名思义,此强制转换将对象“转移”到圆弧。一旦这样做,您就不能再使用cfError
,因为您无法确定ARC何时会释放error
,一旦释放,cfError
就是一个无效指针,使用它很容易使整个应用程序崩溃
如果你投到另一个方向,同样适用。如果你这样做
NSError * error = ...;
CFErrorRef cfError = (__bridge CFErrorRef)error;
ARC仍将管理错误
的内存,这是危险的,如上所述,当ARC决定它可以销毁错误
时,cfError
也将失效。如果您只在当前范围内使用cfError
,这是可以的,但是如果您的CFErrorRef
无论ARC做什么都需要生存,那么您可以执行此强制转换:
NSError * error = ...;
CFErrorRef cfError = (__bridge_retained CFErrorRef)error;
这告诉ARC:“保留错误
一次,然后将错误
转换为cfError
,并且永远不要平衡此初始保留。”
因此,即使error
超出范围,它也不会被ARC释放,因为对象的保留计数器不会变为0,因为该强制转换,它仍然至少为1。现在由您负责内存管理,这意味着一旦完成cfError
,您必须释放它:
CFRelease(cfError);
NSError error=(uu桥NSError*)cfError;给我一个错误“不兼容的类型通过桥转换将'CFErrorRef'转换为NSError*”,您忘记添加指针。它应该是NSError*error=(\uu桥NSError*)cfError;非N错误错误=。。。;我把错误放在了指针上,所以它仍然是同一个错误,你测试了它并成功了吗?这对我来说很有效,我刚刚测试了它。您能用新的代码和错误更新您的问题吗?您是否需要始终将CFErrorRef
显式初始化为nil
?