Как конфертировать из char * в id * с включенной ARC - PullRequest
7 голосов
/ 27 октября 2011

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

Вот код, о котором идет речь:

NSMutableArray* argumentsArray = [NSMutableArray array];

// ... Here I fill argumentsArray with some elements
// And then, I want to construct a "fake" variable argument list

char* fakeArgList = (char*) malloc( sizeof(NSString*) * [argumentsArray count]); 
[argumentsArray getObjects: (id*) fakeArgList];

NSString* content = [[NSString alloc] initWithFormat: formatString arguments:fakeArgList]; 

XCode жалуется на (id ) fakeArgList * casting, говоря:

Преобразование типа указателя без Objective C 'char *' в '_autoreleasing id *' запрещено с ARC

Моя первоначальная теория заключалась в том, что мне просто нужно добавить __unsafe_unretained в (id *) приведение, чтобы сообщить ARC, что я отвечаю за этот блок памяти, и он не должен сохранять / освобождать его, но это не работает и Я не могу понять, как решить эту проблему.

Обновление: Вот полная функция. Он должен взять строку формата printf-стиля и список переменных имен полей внутри .plist и вывести отформатированную строку с данными, загруженными из .plist. То есть, если у меня есть файл .plist с полями "field1" = "foo" и "field2" = 3, и я вызываю [loadStringFromFixture: @"?param1=%@&param2=%d", @"field1", @field2], тогда я должен получить строку "? Param1 = foo & param2 = 3"

- (NSString*) loadStringFromFixture:(NSString*) format, ...
{
    NSString* path = [[NSBundle mainBundle] bundlePath];
    NSString* finalPath = [path stringByAppendingPathComponent:@"MockAPI-Fixtures.plist"];
    NSDictionary* plistData = [NSDictionary dictionaryWithContentsOfFile:finalPath];

    va_list argumentsList;    
    va_start(argumentsList, format);

    NSString* nextArgument;
    NSMutableArray* argumentsArray = [NSMutableArray array];

    while((nextArgument = va_arg(argumentsList, NSString*)))
    {
        [argumentsArray addObject: [plistData objectForKey:nextArgument]];
    }

    NSRange myRange = NSMakeRange(0, [argumentsArray count]);

    id* fakeArgList = (__bridge id *)malloc(sizeof(NSString *) * [argumentsArray count]); 
    [argumentsArray getObjects:fakeArgList range:myRange];
    NSString * content = [[NSString alloc] initWithFormat:formatString
                                                arguments:(__bridge va_list)fakeArgList];

    free(fakeArgList);

    return content;
}

1 Ответ

1 голос
/ 30 октября 2011

Глядя на этот код, он выглядит как довольно грязный хак, но я полагаю, если он работал без ARC, он также должен работать с ARC.Проблема здесь в том, что вы преобразуете из C-указателей в Objective-C указатели, что вы не можете обойтись без мостов:способ сделать это, но так как это для модульного теста, я думаю, что это должно будет сделать.

id __autoreleasing * fakeArgList = (__bridge id __autoreleasing *)malloc(sizeof(NSString *) * [argumentsArray count]);
...