将'NSError * const __strong *'发送到'NSError * __ autoreleasing *'类型的参数会更改指针的保留/释放属性

时间:2015-01-02 14:55:45

标签: ios objective-c automatic-ref-counting

这个问题类似于ios NSError types,但那里描述的解决方案并没有奏效,我相信它并不是我所需要的。

我有一个方法,它执行异步调用,然后调用完成块。当我尝试将NSError **传递给完成块时,我收到此错误:

  

发送' NSError * const __strong *'到类型' NSError的参数   * __ autoreleasing *'更改指针的保留/释放属性

代码如下:

+(void) agentWithGUID:(NSString *) guid completion:(void (^)(AKAgentProfile * agentProfile, NSError ** error)) completionBlock
{
    dispatch_queue_t requestQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(requestQueue, ^{
        NSString * parameterizedUrl = [AKAgentProfileEndPoint stringByAppendingString:guid];
        NSURL *url = [NSURL URLWithString:parameterizedUrl];
        NSData *data = [NSData dataWithContentsOfURL:url];

        NSError * error = nil;

        AKAgentProfile * agentProfile = [[[AKAgentFactory alloc] init] agentProfileWithData:data error:&error];

        dispatch_async(dispatch_get_main_queue(), ^{
            completionBlock(agentProfile,&error);
        });

    });
}

3 个答案:

答案 0 :(得分:6)

你的完成块参数完全是胡说八道。

调用堆栈上有一个变量NSError * err。

然后尝试将err的地址传递给将在主线程中调用的完成块。调用完成块时,您的函数已经返回,并且& err是垃圾。如果完成块试图在那里存储任何东西,它会存储一个NSError *,其中很久以前你的错误变量在堆栈上,很可能会覆盖一个完全不相关的方法的一些有价值的数据。

这只适用于回调块。

答案 1 :(得分:5)

按值传递错误,而不是按引用传递,即将块签名更改为void (^)(AKAgentProfile * agentProfile, NSError * error)并传递error而不是&error

答案 2 :(得分:-1)

您在

中将错误定义为参数
+(void) agentWithGUID:(NSString *) guid completion:(void (^)(AKAgentProfile * agentProfile, NSError ** error)) completionBlock 

然后再次在块中,我建议你重命名块中的那个:

+(void) agentWithGUID:(NSString *) guid completion:(void (^)(AKAgentProfile * agentProfile, NSError ** error)) completionBlock
{
    dispatch_queue_t requestQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(requestQueue, ^{
        NSString * parameterizedUrl = [AKAgentProfileEndPoint stringByAppendingString:guid];
        NSURL *url = [NSURL URLWithString:parameterizedUrl];
        NSData *data = [NSData dataWithContentsOfURL:url];

        NSError * err = nil;

        AKAgentProfile * agentProfile = [[[AKAgentFactory alloc] init] agentProfileWithData:data error:&error];

        dispatch_async(dispatch_get_main_queue(), ^{
            completionBlock(agentProfile,&err);
        });

    });
}