块内函数的返回值

Posted

技术标签:

【中文标题】块内函数的返回值【英文标题】:Return value for function inside a block 【发布时间】:2013-07-14 18:49:29 【问题描述】:

我正在使用 AFNetworking 从服务器获取数据:

-(NSArray)some function 
    AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
        success: ^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) 
            NSArray *jsonArray =[JSON valueForKey:@"posts"];
        
        failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) 

所以我在这里要做的就是将 jsonArray 返回给函数。显然 return 不起作用。

【问题讨论】:

你不能这样做。由于您正在处理异步调用,因此您的 some function 方法将在返回值之前很久就返回。 我建议你退后一步,想想你的代码做了什么。你很快就会意识到你想要的东西没有意义。 您可以将块传递给函数,该函数将在成功或错误时执行。 【参考方案1】:

您不能使用完成块为您的方法创建返回值。 AFJSONRequestOperation 异步执行其工作。 someFunction 将在操作仍在进行时返回。成功和失败块是您如何在需要的地方获得结果值。

这里的一个选项是将调用者作为参数传递给您的包装方法,以便完成块可以将数组交出。

- (void)goFetch:(id)caller

    AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
    success: ^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) 

        [caller takeThisArrayAndShoveIt:[JSON valueForKey:@"posts"]];
    
    failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) 

您还可以让您的调用者创建并传递一个 Block 以在成功时运行。然后goFetch: 不再需要知道调用者上存在哪些属性。

- (void)goFetch:(void(^)(NSArray *))completion

    AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
    success: ^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) 
        if( completion ) completion([JSON valueForKey:@"posts"]);
    
    failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) 

【讨论】:

【参考方案2】:

正如其他人所说,在处理异步调用时不能这样做。您可以将完成块作为参数传递,而不是返回预期的数组

typedef void (^Completion)(NSArray* array, NSError *error);

-(void)someFunctionWithBlock:(Completion)block 
    AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
        success: ^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) 
            NSArray *jsonArray =[JSON valueForKey:@"posts"];
            if (block) block(jsonArray, nil);
        
        failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON)  
            if (block) block(nil, error); 
        

然后你称之为 someFunction。此代码还将为您进行适当的错误处理。

[yourClassInstance someFunctionWithBlock:^(NSArray* array, NSError *error) 
   if (error) 
      NSLog(%@"Oops error: %@",error.localizedDescription);
    else 
      //do what you want with the returned array here.
   
];

【讨论】:

【参考方案3】:

我遇到了这种问题,用下面这个方法解决。 我看到上面使用块的答案。但这个方案更适合当时的情况。 该方法的逻辑很简单。您需要将对象及其方法作为参数发送,并在请求完成后调用该方法。 希望对您有所帮助。

+(void)request:(NSString *)link parameters:(NSDictionary *)params  forInstance:(id)instance returns:(SEL)returnValue

    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
    [manager GET:link
      parameters:params
         success:^(AFHTTPRequestOperation *operation, id responseObject)
     
         [instance performSelector:returnValue withObject: responseObject];
     
         failure:^(AFHTTPRequestOperation *operation, NSError *error)
     
         [instance performSelector:returnValue withObject:nil];
         //NSLog(@"Error: %@", error);
     ];

【讨论】:

以上是关于块内函数的返回值的主要内容,如果未能解决你的问题,请参考以下文章

AFNetworking 可以同步返回数据(在一个块内)吗?

js 如何创建带返回值的函数

C语言如何写有返回值的函数

什么是函数返回值?

JAVA里的函数返回值,可以返回几个?

函数参数,返回值,递归函数