2

我是在 iOS 中使用块的新手,我认为这可能是我问题的症结所在。

我只想构建一个简单的静态 DataManager 类,它的唯一工作是从我的 Restful 服务中获取数据。

我会从我所有的各种 UIViewControllers(或 collectionview/table 控制器)中调用它

在我的课堂上,我有一个看起来像这样的函数

+ (NSArray *) SearchByKeyword: (NSString*) keyword {
    __block NSArray* searchResults = [[NSArray alloc] init];
    NSString *baseURL = @"http://someURL.com/api/search";
    NSString *requestURL = [baseURL stringByAppendingString:keyword];
    AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:baseURL]];
    NSMutableURLRequest *request = [httpClient requestWithMethod:@"GET"
                                                      path:requestURL
                                                      parameters:nil];
    AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
        searchResults = [JSON valueForKeyPath:@""];
    } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
        NSLog(@"Request Failed with Error: %@, %@", error, error.userInfo);
    }];
    [operation start];
    return searchResults;
}

但是,这会一直返回零数据。有人可以建议这样做的正确方法吗?

4

2 回答 2

7

您正在尝试使用异步任务(JSON 操作)的结果作为同步方法调用的返回值,这就是您没有获得数据的原因。

你可以为你的视图控制器提供一个接受完成块和失败块的 API,类似于 AF 网络。然后,视图控制器可以在将结果传递到块时对其执行所需的操作。

根据您的问题修改您的代码:

typedef void (^SearchCompletionBlock)(NSArray *results);
typedef void (^SearchFailureBlock)(NSError *error);

+ (void)searchByKeyword:(NSString*)keyword completionBlock:(SearchCompletionBlock)completionBlock failureBlock:(SearchFailureBlock)failureBlock;
{
    NSString *baseURL = @"http://someURL.com/api/search";
    NSString *requestURL = [baseURL stringByAppendingString:keyword];
    AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:baseURL]];
    NSMutableURLRequest *request = [httpClient requestWithMethod:@"GET"
                                                            path:requestURL
                                                      parameters:nil];
    AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
                                                                                        success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
                                                                                            if (completionBlock) {
                                                                                                completionBlockc([JSON valueForKeyPath:@""]);
                                                                                            }
                                                                                        } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
                                                                                            NSLog(@"Request Failed with Error: %@, %@", error, error.userInfo);
                                                                                            if (failureBlock) {
                                                                                                failureBlock(error);
                                                                                            }
                                                                                        }];
    [operation start];
}

然后客户端可以传递存储结果并重新加载他们的视图的完成块。就像是:

^ (NSArray *results) {
    self.results = results;
    [self.tableView reloadData];
}
于 2013-03-01T06:58:31.677 回答
1

您的 JSON 请求操作是异步的,这意味着它将启动请求 ( [operations start],然后立即返回您的结果,该结果将为空。当完成块运行时,它会分配您的数据,但什么也不做。您的搜索方法可以t 返回一个对象,除非它等待请求完成。

你有几个选择:

  1. 将完成块传递给对结果执行某些操作的搜索方法。一旦完成所有特定于服务的内容(处理 JSON 等),就会在请求的完成块中调用完成块。(阻止启动!)

  2. 让请求的完成块分配数据管理器的属性,然后调用委托方法或通知让其他人知道结果可用。

我更喜欢选项1。

于 2013-03-01T06:53:11.627 回答