返回方法失败在一个完成块

在这里输入图像说明 我有这个问题,为什么我不能RETURN值:

 - (NSArray *)SQLRetrieve:(NSString *)barID { self.client = [MSClient clientWithApplicationURLString:@"https://outnight-mobile.azure-mobile.net/" applicationKey:@"okYeRGfBagYrsbkaqWIRObeDtktjkF10"]; [self.client invokeAPI:@"photos" body:barID HTTPMethod:@"POST" parameters:nil headers:nil completion:^(id result, NSHTTPURLResponse *response, NSError *error) { if (error) { NSLog(@"Error %@", error ); } else { NSString *string = [NSString stringWithFormat:@"%@", [result objectForKey:@"rows"]]; NSString *stringWithoutbracketsend = [string stringByReplacingOccurrencesOfString:@")" withString:@""]; NSString *stringWithoutbracketsfront = [stringWithoutbracketsend stringByReplacingOccurrencesOfString:@"(" withString:@""]; NSString *completion = [stringWithoutbracketsfront stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; NSString *newStr = [completion substringFromIndex:1]; NSString *finalstring = [newStr substringToIndex:newStr.length-(newStr.length>0)]; //NSLog(@"%@", finalstring); [MyArray addObject:finalstring]; NSLog(@"%@", [MyArray objectAtIndex:0]); return finalstring; } }]; 

它后来出现了一个错误。 我附上了错误的图像。 只是完全地,完全地丢失了 – 有人能告诉我们问题是什么,这样可以让我们印象深刻

您试图从完成块中返回一个值,但该块有一个void返回types。 这就是编译器抱怨的原因。

如果你希望这个方法从这个(可能是)asynchronous执行的完成块中返回值,你不应该尝试返回块内的值,而是你应该自己使用一个asynchronous完成块模式:

 - (void)SQLRetrieve:(NSString *)barID completion:(void (^)(NSString *string, NSError *error))completion { self.client = [MSClient clientWithApplicationURLString:@"https://outnight-mobile.azure-mobile.net/" applicationKey:@"..."]; [self.client invokeAPI:@"photos" body:barID HTTPMethod:@"POST" parameters:nil headers:nil completion:^(id result, NSHTTPURLResponse *response, NSError *error) { if (error) { if (completion) completion(nil, error); // or, you might want to explicitly dispatch that completion block back to the main queue: // // if (completion) // dispatch_async(dispatch_get_main_queue(), ^{ // completion(nil, error); // }); } else { NSString *string = [NSString stringWithFormat:@"%@", [result objectForKey:@"rows"]]; NSString *stringWithoutbracketsend = [string stringByReplacingOccurrencesOfString:@")" withString:@""]; NSString *stringWithoutbracketsfront = [stringWithoutbracketsend stringByReplacingOccurrencesOfString:@"(" withString:@""]; NSString *completion = [stringWithoutbracketsfront stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; NSString *newStr = [completion substringFromIndex:1]; NSString *finalstring = [newStr substringToIndex:newStr.length-(newStr.length>0)]; if (completion) completion(finalstring, nil); // or, you might want to explicitly dispatch that completion block back to the main queue: // // if (completion) // dispatch_async(dispatch_get_main_queue(), ^{ // completion(finalstring, nil); // }); } }]; } 

然后,你会像这样调用它:

 [self SQLRetrieve:@"your-bar-id" completion:^(NSString *string, NSError *error) { if (error) { // do whatever you want upon error NSLog(@"Error %@", error ); } else { // do whatever you want with the string, for example [MyArray addObject:string]; } }]; 

我不知道如何协调你声明一个声明返回一个数组的方法,但你似乎返回一个string的事实,所以我简单地推测你真的打算后者(如你可以从我的代码示例看到的)。 如果你真的想要返回数组,那么只要改变这个完成块来传回一个数组,然后切换到实际传回该数组的代码。

一个相关的,但更微妙的问题是,你似乎是你的原始代码示例返回一个string,但也添加到MyArray的string,你不在这个代码示例其他地方引用。 您应该非常谨慎地从asynchronous调用的代码块中更新模型对象。 (因为虽然这段代码是asynchronous运行的,但是你可能有一个继续引用MyArray的UI,如果你在中途修改它,可能会感到困惑)。将SQLRetrieve传递给MyArray的块可能更安全一些,就像我上面所说的 如果invokeAPI的完成块不能保证在主队列上运行,你可能需要显式地将你自己的完成块分派回主队列。 您要确保不仅更新主队列上的UI,而且还可能要确保只更新主队列中的模型对象(这是避免同步错误的最简单方法)。

期望的块types的返回types是void,而不是NSString,正如你通过添加一个return所指定的那样。 你不能返回一个值。

首先,您将在哪里存储回报? 通常返回被分配给调用中的variables:

 NSString *string = [NSString alloc] init]; 

[[NSString alloc] init]的返回被分配给*string 。 在你的情况下:

 [self.client invokeAPI ... 

回报没有变化,所以你的回报毫无意义。

现在的错误:它说你正试图发送返回types为NSString*的函数返回types为voidMSAPIBlock aka (void(^) )函数。asynchronous块不能返回一个variables到您的代码,因为他们可以完成后你的代码在你的情况下,我认为你需要调度到一个单独的函数来处理你的finalString 。在你的完成块的末尾添加:

 dispatch_async( dispatch_get_main_queue(), ^{ [self doSomethingWithReturnString:finalString]; }); 

编辑:添加完整的代码为您的function

 - (NSArray *)SQLRetrieve:(NSString *)barID { self.client = [MSClient clientWithApplicationURLString:@"https://outnight-mobile.azure-mobile.net/" applicationKey:@"okYeRGfBagYrsbkaqWIRObeDtktjkF10"]; [self.client invokeAPI:@"photos" body:barID HTTPMethod:@"POST" parameters:nil headers:nil completion:^(id result, NSHTTPURLResponse *response, NSError *error) { if (error) { NSLog(@"Error %@", error ); } else { NSString *string = [NSString stringWithFormat:@"%@", [result objectForKey:@"rows"]]; NSString *stringWithoutbracketsend = [string stringByReplacingOccurrencesOfString:@")" withString:@""]; NSString *stringWithoutbracketsfront = [stringWithoutbracketsend stringByReplacingOccurrencesOfString:@"(" withString:@""]; NSString *completion = [stringWithoutbracketsfront stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; NSString *newStr = [completion substringFromIndex:1]; NSString *finalstring = [newStr substringToIndex:newStr.length-(newStr.length>0)]; //NSLog(@"%@", finalstring); [MyArray addObject:finalstring]; NSLog(@"%@", [MyArray objectAtIndex:0]); dispatch_async( dispatch_get_main_queue(), ^{ [self doSomethingWithReturnString:finalString]; }); } }]; } -(void)doSomethingWithReturnString:(NSString*)string { //Do whatever you need to with the return string here, //if you don't need it anymore then no need to call this function //(you already added it to your array) }