对于我的应用,我需要从服务器加载不同的数据,因此我需要发出几个GET
个请求。
对于每个GET请求,我需要将数据保存在我的CoreData中......所以我需要回调或每个操作的成功块。
我尝试了几件事,但我无法使它发挥作用。
当我执行单个GET
请求时:
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:[NSString stringWithFormat:@"%@/api/actors", [NSString stringWithUTF8String:kBaseURL]] parameters:nil
success:^(AFHTTPRequestOperation *operation, id responseObject) {
// Core Data saving
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Error: %@", error);
}];
如何制作多个GET
并等待我的所有请求都完成?
如果有人给我写了一个解决方案......它是否适用于其他类型的请求? (POST,DELETE,PUT ......等)
由于
答案 0 :(得分:3)
dispatch_group
可能是一种可能的解决方案,同时保持令人难以置信的通用结构,并且还可以处理您想要的任何类型的请求。
而不是重新创建一个好例子,commandshift has a good writeup explaining them and a great example of how to use them
答案 1 :(得分:2)
AFHTTPRequestOperation
类是AFURLConnectionOperation
的子类,它提供了方法
+ (NSArray *)batchOfRequestOperations:(NSArray *)operations progressBlock:(void ( ^ ) ( NSUInteger numberOfFinishedOperations , NSUInteger totalNumberOfOperations ))progressBlock completionBlock:(void ( ^ ) ( NSArray *operations ))completionBlock
此方法需要NSArray
个操作和两个块,一个用于更新进度(如果需要),另一个用于完成时调用。此方法负责您必须手动完成的完成组/完成队列舞蹈。操作完成后,将调用完成块,您可以使用AFHTTPRequestOperation
和AFURLConnectionOperation
的属性循环操作以获取响应数据并将其保存到Core Data对象。
您可以按如下方式创建操作:
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
operation.responseSerializer = // set the serializer if you need something other than JSON
如果您希望将响应对象存储在私有属性中,然后在完成块中访问它们,然后将它们保存到Core Data对象,也可以设置完成块属性。 。这将简化完成块中所需的逻辑。
为了让操作运行,您需要创建一个NSOperationQueue并添加操作。它将如下:
NSArray *operations = @[op1, op2, op3...];
NSOperationQueue *downloadQueue = [[NSOperationQueue alloc] init];
[downloadQueue addOperations:operations waitUntilFinished:NO];
答案 2 :(得分:1)
在这种情况下,您可以编写一个更通用的方法,以递归方式遍历包含您的请求路径的数组:
// --------------------------------------------------------
// Header file
// --------------------------------------------------------
@property (nonatomic, strong) NSMutableArray *arrRequestURLs;
// --------------------------------------------------------
// Implementation file
// --------------------------------------------------------
-(void)viewDidLoad
{
...
self.arrRequestURLs = [[NSMutableArray alloc] init];
[self.arrRequestURLS addObject:@[@"http://api.myserver.com/api/actors"];
[self.arrRequestURLS addObject:@[@"http://api.myserver.com/api/directors"];
[self.arrRequestURLS addObject:@[@"http://api.myserver.com/api/photographers"];
[self performRequestQueue:self.arrRequestURLS onSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
// all request completed successfully do something here
} onFailure: ^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Failed to complete all request");
} onEachSuccess: ^(AFHTTPRequestOperation *operation, id *responseObject, NSString *sourceRequestURL) {
// Scroll down to bottom see method implementation
[self handleIntermediateSuccessOperation:operation
Response:responseObject
ForRequestURL:sourceRequestURL];
}];
}
// ------------------------------------------------------------------------------
// A recursive method that executes each request string in the passed in array
// and removes from array after successfully performing request, then calls itself
// again until arrRequestURLs is empty.
// ------------------------------------------------------------------------------
-(void)performRequestQueue:(NSMutableArray *)arrRequestURLs
onSuccess:(void(^)(AFHTTPRequestOperation *operation, id responseObject))success
onFailure:(void(^)(AFHTTPRequestOperation *operation, NSError *error))failure
onEachSuccess: (void(^)(AFHTTPRequestOperation *operation, id *responseObject, NSString *sourceRequestURL))intermediateSuccess
{
if(arrRequestURLs.count > 0)
{
// make request
[manager GET:arrRequestURLs[0] parameters:nil
success:^(AFHTTPRequestOperation *operation, id responseObject) {
// call intermediate success block if any
if(intermediateSuccess)
{
intermediateSuccess(operation, responseObject, arrRequestURLs[0]);
}
// remove the current str from array
[arrRequestURLs removeObjectAtIndex:0];
// check to see if there more request
if(arrRequestURLs.count > 0)
{
// recursively call this method again to perform next URL string from array
[self performRequestQueue:arrRequestURLs onSuccess:success onFailure:failure];
}
else
{
// no more request in arrRequestURLs, call finish block if any
if(success)
{
success(operation, responseObject);
}
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
if(failure)
{
failure(operation, error);
}
}];
}
}
// ------------------------------------------------------------------------------
// This method here handles the in-between success block for each operation
// including the last final success block.
// ------------------------------------------------------------------------------
-(void)handleIntermediateSuccessOperation:(AFHTTPRequestOperation *)operation
Response:(id)responseObject
ForRequestURL:(NSString *)sourceRequestURL
{
// ------------------------------------------------------------
// Alternative, you can probably use a for loop here to get the
// matching array index from self.arrRequestURLs and use it.
// ------------------------------------------------------------
if([sourceRequestURL isEqualToString:self.arrRequestURLs[0]])
{
// success block for actors, do something here
}
else if([sourceRequestURL isEqualToString:self.arrRequestURLs[1]])
{
// success block for directors, do something here
}
else
{
// success block for photographers, do something here
}
}
您可以链接您的请求:
[manager GET:[NSString stringWithFormat:@"%@/api/actors", [NSString stringWithUTF8String:kBaseURL]] parameters:nil
success:^(AFHTTPRequestOperation *operation, id responseObject) {
// Core Data saving
[manager GET:[NSString stringWithFormat:@"%@/api/directors", [NSString stringWithUTF8String:kBaseURL]] parameters:nil
success:^(AFHTTPRequestOperation *operation, id responseObject) {
// Core Data saving
[manager GET:[NSString stringWithFormat:@"%@/api/photographers", [NSString stringWithUTF8String:kBaseURL]] parameters:nil
success:^(AFHTTPRequestOperation *operation, id responseObject) {
// Core Data saving
// ---------------------------------------------
// Finished downloading all data
// do something here
// ---------------------------------------------
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Error: %@", error);
}];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Error: %@", error);
}];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Error: %@", error);
}];
答案 3 :(得分:0)
如果您只有少量请求,则可以在成功块中嵌套下一个操作。如果您的操作次数少于几次,我建议您使用NSOperationQueue。
答案 4 :(得分:0)
试试这个:
NSInteger successCount;
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:someUrl parameters:nil
success:^(AFHTTPRequestOperation *operation, id responseObject) {
successCount++;
if(successCount == 3){
//do stuff
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Error: %@", error);
}];
[manager GET:someUrl parameters:nil
success:^(AFHTTPRequestOperation *operation, id responseObject) {
successCount++;
if(successCount == 3){
//do stuff
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Error: %@", error);
}];
[manager GET:someUrl parameters:nil
success:^(AFHTTPRequestOperation *operation, id responseObject) {
successCount++;
if(successCount == 3){
//do stuff
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Error: %@", error);
}];
答案 5 :(得分:0)
我找到了AFNetworking
的一个很好的解决方案,我可以做我想做的事情:
NSArray *operations = [AFURLConnectionOperation batchOfRequestOperations:mutableOperations progressBlock:^(NSUInteger numberOfFinishedOperations, NSUInteger totalNumberOfOperations) {
NSLog(@"%lu of %lu complete", numberOfFinishedOperations, totalNumberOfOperations);
} completionBlock:^(NSArray *operations) {
[self.delegate dataRefreshingDone];
}];
[[NSOperationQueue mainQueue] addOperations:operations waitUntilFinished:NO];
它将逐个执行我的所有GET
操作。
我根据getter
创建了一个特殊的url
来创建一个操作。
- (AFHTTPRequestOperation *)operationGetForUrl:(NSString *)url
{
NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:@"%@/api/%@", [NSString stringWithUTF8String:kBaseURL], url]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
[request setHTTPMethod:@"GET"];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
operation.responseSerializer = [AFJSONResponseSerializer serializer];
[operation.responseSerializer setAcceptableContentTypes: [operation.responseSerializer.acceptableContentTypes setByAddingObject:@"text/html"]];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
// YOUR SUCCESS BLOCK
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
// FAILURE BLOCK
}];
return operation;
}
正如你所看到的,对于每个操作,我都有一个成功的块,它可以做一些通用的东西......或者你可以制作具体的操作getter。