如何将AFNetworking AFJSONRequestOperation包装到单独的datamanager类中

时间:2013-03-01 01:35:01

标签: ios objective-c-blocks afnetworking

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

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

我会从各种各样的UIViewControllers(或collectionview / table controllers)

中调用它

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

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

然而,这会不断返回零数据。有人可以提出正确的方法吗?

2 个答案:

答案 0 :(得分:7)

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

您可以为视图控制器提供一个API,该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];
}

答案 1 :(得分:1)

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

你有几个选择:

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

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

  3. 我更喜欢选项1.