Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/sharepoint/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 使用圆弧将CFErrorRef投射到N错误(或相反)上_Objective C_Cocoa_Automatic Ref Counting - Fatal编程技术网

Objective c 使用圆弧将CFErrorRef投射到N错误(或相反)上

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,

我曾经像这样对CFErrorRef抛出一个NSError,并在SMJobBless中使用它

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