ARC [rewriter] NSInvocation的setArgument与不具有__unsafe_unretained的所有权的对象一起使用是不安全的

时间:2012-09-21 12:24:45

标签: automatic-ref-counting nsinvocation

我一直将我的项目转换为ARC,并且我遇到了这个错误。

& object,& invocation和& callerToRetain向我显示错误“[rewriter] NSInvocation的setArgument与安全性不同于__unsafe_unretained的对象一起使用是不安全的”

+ (void)performSelector:(SEL)selector onTarget:(id *)target withObject:(id)object amount:(void *)amount callerToRetain:(id)callerToRetain{if ([*target respondsToSelector:selector]) {
    NSMethodSignature *signature = nil;
    signature = [*target methodSignatureForSelector:selector];
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];

    [invocation setSelector:selector];

    int argumentNumber = 2;

    // If we got an object parameter, we pass a pointer to the object pointer
    if (object) {
        [invocation setArgument:&object atIndex:argumentNumber];
        argumentNumber++;
    }

    // For the amount we'll just pass the pointer directly so NSInvocation will call the method using the number itself rather than a pointer to it
    if (amount) {
        [invocation setArgument:amount atIndex:argumentNumber];
    }

    SEL callback = @selector(performInvocation:onTarget:releasingObject:);
    NSMethodSignature *cbSignature = [ASIHTTPRequest methodSignatureForSelector:callback];
    NSInvocation *cbInvocation = [NSInvocation invocationWithMethodSignature:cbSignature];
    [cbInvocation setSelector:callback];
    [cbInvocation setTarget:self];
    [cbInvocation setArgument:&invocation atIndex:2];
    [cbInvocation setArgument:&target atIndex:3];
    if (callerToRetain) {
        [cbInvocation setArgument:&callerToRetain atIndex:4];
    }

    CFRetain(invocation);

    // Used to pass in a request that we must retain until after the call
    // We're using CFRetain rather than [callerToRetain retain] so things to avoid earthquakes when using garbage collection
    if (callerToRetain) {
        CFRetain(callerToRetain);
    }
    [cbInvocation performSelectorOnMainThread:@selector(invoke) withObject:nil waitUntilDone:[NSThread isMainThread]];
}}

请帮帮我。

1 个答案:

答案 0 :(得分:5)

默认情况下,NSInvocation不保留或复制给定的参数以提高效率,因此作为参数传递的每个对象在调用调用时仍必须存在。这意味着传递给-setArgument:atIndex:的指针被处理为__unsafe_unretained。

如果您在ARC中使用NSInvocation,最简单的方法是

  1. 在创建调用对象后调用[invocation retainArguments]。这意味着调用将保留给定的参数。
  2. 传递参​​数时,将它们转换为__unsafe_unretained
  3. 没有第3步。