2015-03-27 3 views
0

Мне нужен способ, чтобы преобразовать NSArray в нуль список совместимого с опцией аргументы DADiskMountWithArguments прекращается.Преобразование NSArray в CFStringRef *

Документация указывает опцию аргумента как «список с нулевым завершением» типа CFStringRef arguments[].

Я создал метод Mount, который я хочу передать NSArray с аргументами, и в моем методе мне нужно преобразовать NSArray в CFStringRef *.

Я пробовал себя, но у меня всегда возникают проблемы с ARC, и я пока не смог найти хороший способ сделать это.

Я посмотрел на проект Disk-Арбитре в GitHub https://github.com/aburgh/Disk-Arbitrator/blob/master/Source/Disk.m для вдохновения, и создатель этого приложения использует этот метод:

- (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); 
} 

Но это не допускается в АРК, и я не могу найти способ сделать это.

Обновление для большей наглядности:

Эта линия:

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

дает следующее сообщение об ошибке:

Implicit conversion of a non-Objective-C pointer type 'void *' to '__strong id *' is disallowed with ARC

Pointer to non-const type 'id' with no explicit ownership.

Чтобы исправить, что я пытаюсь сделать это:

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

Затем эта линия:

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

дает следующие ошибки:

[ERROR] Implicit conversion of an Objective-C pointer to '__unsafe_unretained id *' is disallowed with ARC

[WARN] Incompatible pointer types sending '__string id' to parameter of type '__unsafe_unretained id *'

Декларация -getObjects: диапазон: выглядеть следующим образом:

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

Таким образом, с ошибкой сообщение, которое я получил, я предполагаю, что мне нужно передать '__unsafe_unretained id *' в 'getObjects: (id []) aBuffer'. Таким образом, чтобы исправить это я объявляю мое удостоверение личности, как __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 я получаю следующее сообщение об ошибке:

Cast of an Objective-C pointer to 'CFStringRef *' (aka 'const struct __CFString **) is disallowed with ARC

так вот я застрял, как я не был в состоянии исправить эту ошибку, и я не знаю, если Я сделал ошибки раньше или, если я не нашел правильный путь, отправьте CFStringRef, поэтому я решил попросить руководство здесь.

Вот как это выглядит в контексте, где арг является 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 *

+0

Что вы подразумеваете под ", что запрещено в ARC"? Что не допускается? Какая же линия и ошибка? –

+0

Да, извините за неясность. Я обновил свой вопрос с проблемными линиями. –

ответ

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() не дает вам права собственности на возвращаемые значения.

+0

Спасибо, это отлично работает. Я изучу ваши изменения, чтобы лучше понять это. –

+0

Добро пожаловать. 'NSArray' является бесплатным мостом для своей основной компании-учредителя« CFArray ». Типы Core Foundation не управляются ARC. Перейдя на API Core Foundation, вы обойдете проблемы с ARC. Для передачи 'NSArray' в' CFArrayGetValues ​​() 'существует только одна команда' __bridge', которая не связана с проблемами управления памятью. –

Смежные вопросы