0

我需要一种将NSArray转换为与DADiskMountWithArguments的参数选项兼容的空终止列表的方法。

该文档将参数选项指定为类型的“空终止列表” CFStringRef arguments[]

我创建了一个 Mount 方法,我想通过参数传递一个NSArray,并且在我的方法中我需要将NSArray转换为 CFStringRef *。

我已经尝试过自己,但我总是遇到 ARC 的麻烦,而且我还没有找到任何好的方法来做到这一点。

我查看了 GitHub https://github.com/aburgh/Disk-Arbitrator/blob/master/Source/Disk.m中的 Disk-Arbitrator 项目以获取灵感,该应用程序的创建者使用此方法:

- (void)mountAtPath:(NSString *)path withArguments:(NSArray *)args
{
    NSAssert(self.isMountable, @"Disk isn't mountable.");
    NSAssert(self.isMounted == NO, @"Disk is already mounted.");

    self.isMounting = YES;

    Log(LOG_DEBUG, @"%s mount %@ at mountpoint: %@ arguments: %@", __func__, BSDName, path, args.description);

    // ensure arg list is NULL terminated
    id *argv = calloc(args.count + 1, sizeof(id));

    [args getObjects:argv range:NSMakeRange(0, args.count)];

    NSURL *url = path ? [NSURL fileURLWithPath:path.stringByExpandingTildeInPath] : NULL;

    DADiskMountWithArguments((DADiskRef) disk, (CFURLRef) url, kDADiskMountOptionDefault,
                         DiskMountCallback, self, (CFStringRef *)argv);

    free(argv);
}

但这在 ARC 中是不允许的,我找不到办法。

更新以获得更好的清晰度:

这一行:

id *argv = calloc(args.count + 1, sizeof(id));

给出以下错误消息:

ARC 不允许将非 Objective-C 指针类型“void *”隐式转换为“__strong id *”

指向没有明确所有权的非常量类型“id”的指针。

为了解决这个问题,我尝试这样做:

id argv = (__bridge id)(calloc(args.count + 1, sizeof(id)));

然后这一行:

[args getObjects:argv range:NSMakeRange(0, args.count)];

给出以下错误:

[错误] ARC 不允许将 Objective-C 指针隐式转换为“__unsafe_unretained id *”

[警告]不兼容的指针类型将“__string id”发送到“__unsafe_unretained id *”类型的参数

-getObjects:range:的声明如下所示:

- (void)getObjects:(id [])aBuffer range:(NSRange)aRange

因此,从我收到的错误消息中,我假设我必须将“__unsafe_unretained id *”传递给“getObjects:(id [])aBuffer”。所以要解决这个问题,我将我的 id 声明为 __unsafe_unretained,如下所示:

__unsafe_unretained id argv = (__bridge __unsafe_unretained id)(calloc(args.count + 1, sizeof(id)));

并像这样更新这一行:

[args getObjects:&argv range:NSMakeRange(0, args.count)];

现在我没有任何错误,但是在调用DADiskMountWithArguments 时,我收到以下错误:

ARC 不允许将 Objective-C 指针转换为“CFStringRef *”(又名“const struct __CFString **”)

所以在这里我卡住了,因为我无法修复这个错误,我不知道我之前是否犯了错误,或者我没有找到正确的方式发送 CFStringRef,因此我决定在这里寻求指导。

这是它在上下文中的样子,其中 args 是之前声明的NSArray

__unsafe_unretained id argv = (__bridge __unsafe_unretained id)(calloc(args.count + 1, sizeof(id)));

[args getObjects:&argv range:NSMakeRange(0, args.count)];

DADiskMountWithArguments((DADiskRef) disk, (__bridge CFURLRef) url, kDADiskMountOptionDefault, NULL, (__bridge void *)self, (CFStringRef *)argv );

所以我的问题是,如何使这种方法对 ARC 友好,或者是否有另一种/更好的方法可以从NSArray到以 NULL 结尾的 CFStringRef *

4

1 回答 1

1

尝试这个:

CFStringRef *argv = calloc(args.count + 1, sizeof(CFStringRef));
CFArrayGetValues((__bridge CFArrayRef)args, CFRangeMake(0, args.count), (const void **)argv );
DADiskMountWithArguments((DADiskRef) disk, (CFURLRef) url, kDADiskMountOptionDefault,
                     DiskMountCallback, self, argv);
free(argv);

没有 Core Foundation/Cocoa 内存管理问题,因为CFArrayGetValues()不给你返回值的所有权。

于 2015-03-28T12:06:16.190 回答