如何在启用ARC的情况下将char*转换为id*

Ale*_*kov 8 objective-c automatic-ref-counting

我正在尝试构建"假"变量参数列表,使用此处描述的技术,但对于启用ARC的项目,我无法弄清楚如何摆脱我得到的错误.

这是有问题的代码:

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]; 
Run Code Online (Sandbox Code Playgroud)

XCode抱怨(id)fakeArgList*cast,说:

使用ARC不允许将非Objective-C指针类型'char*'强制转换为'_autoreleasing id*'

我最初的理论是,我只需要将__unsafe_unretained添加到(id*)转换,告诉ARC我负责该内存块,它不应该保留/释放它,但这不起作用,我可以'弄清楚如何解决这个问题.

更新:这是完整的功能.它应该在.plist中采用printf样式的格式字符串和字段名称的变量列表,并输出带有从.plist加载的数据的格式化字符串.即,如果我有一个带字段"field1"="foo"和"field2"= 3的.plist文件,[loadStringFromFixture: @"?param1=%@&param2=%d", @"field1", @field2] 然后我调用那么我应该得到字符串"?param1 = foo¶m2 = 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;
}
Run Code Online (Sandbox Code Playgroud)

Ale*_*hol 2

看看这段代码,它似乎是一个相当肮脏的黑客,但我想如果它在没有 ARC 的情况下工作,它也应该ARC 一起工作。这里的问题是你正在从 C 指针转换为 Objective-C 指针,如果没有桥接就无法做到这一点:

NSMutableArray * argumentsArray = [NSMutableArray array];

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

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);
Run Code Online (Sandbox Code Playgroud)

这仍然很丑陋,我真的希望有更好的方法来做到这一点,但由于它是用于单元测试,我想它必须这样做。

编辑:桥接演员可能应该像这样完成:

id __autoreleasing * fakeArgList = (__bridge id __autoreleasing *)malloc(sizeof(NSString *) * [argumentsArray count]);
Run Code Online (Sandbox Code Playgroud)