return方法在完成块中失败

时间:2014-02-12 14:00:40

标签: ios objective-c nsstring

enter image description here我遇到了这个问题,为什么我不能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;
                    }
                }];

之后出现错误。 我附上了错误的图像。只是彻底而彻底地迷失了 - 有人可以通过告诉我们问题是什么来打动我们

3 个答案:

答案 0 :(得分:2)

您正在尝试从完成块内部返回一个值,但该块具有void返回类型。这就是编译器抱怨的原因。

如果您希望此方法从此(可能是)异步执行的完成块中返回值,则不应尝试从块中返回值,而应自行使用异步完成块模式:

- (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];
    }
}];

我不知道如何调和你声明一个声明返回一个数组但是你似乎返回一个字符串的方法的事实,所以我只是假设你真的想要后者(你可以从我的代码示例中看到) )。如果你真的想要返回数组,那么只需更改完成块以传回一个数组,然后更改为代码以实际传回该数组。

这里一个相关但更微妙的问题是,您似乎是原始代码示例返回一个字符串,但也将字符串添加到MyArray,您在此代码示例的其他位置未引用该字符串。您应该非常谨慎地从异步调用的代码块中更新模型对象。 (因为虽然此代码是异步运行的,但您可能会有一个继续引用MyArray的UI,如果您在流中更改它,可能会感到困惑。)将传递给您的块可能更安全SQLRetrieve更新MyArray,就像我上面一样。如果无法保证invokeAPI的完成块在主队列上运行,您可能希望将自己的完成块显式调度回主队列。您希望确保不仅更新主队列上的UI,而且您可能还希望确保仅更新主队列中的模型对象(这是避免同步错误的最简单方法)。

答案 1 :(得分:1)

预期块类型的返回类型为void,而不是通过添加返回指定的NSString。您无法返回值。

答案 2 :(得分:0)

首先在哪里存储退货?通常将返回分配给调用中的变量:

NSString *string = [NSString alloc] init];

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

[self.client invokeAPI ...

没有分配回报的变量,所以你的回报毫无意义。

现在出现错误:它表示您正在尝试将返回类型为NSString*的函数发送到返回类型voidMSAPIBlock aka (void(^))的函数。异步块无法向代码返回变量,因为它们可以在代码完成后完成。在您的情况下,我认为您需要发送一个单独的功能来处理您的finalString。在完成块结束时添加:

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

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

- (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)
}