我正在编写一个连接Web的应用程序,需要执行多个异步请求来加载依赖关系树中所需的数据。
图1。
出于可视化目的,请考虑使用ASIHTTPRequests A,B,C,D,E和F的示例:
A的网址取决于B和C的结果,
和B的url取决于D,E和F的结果。
B和C可以同时计算,D,E和F也可以计算。
NSOperationQueue = [(D,E,F),(B,C),A]
到目前为止,我已经创建了一个包含ASIHTTPRequests依赖树的NSOperationQueue。但是,ASIHTTPRequests的URL应该取决于先前操作的结果,而且,现在它们不会。
问题:将多个NSOperations执行的计算结果传递给依赖于它们的NSOperation的最佳方法是什么,以及如何使用ASIHTTPRequests进行设置?
提前致谢, Julian Ceipek
答案 0 :(得分:1)
我会做以下事情。
首先,排队:
D,E,F和C
在D,E&的requestFinished委托回调中F,检查其他所有3个请求是否都已完成,如果是,则发送B。
为B& S的回调做同样的事情。 C - 如果他们都完成了,发送A。
您需要某种对象,这些对象由所有请求共享,以存储先前请求的结果/状态。
答案 1 :(得分:1)
我最终解决了这个问题,方法是将ASIHTTPRequest包装在一个自定义的NSOperation对象中,该对象以自定义请求B包含指向D,E和F的ASIHTTPRequest UserInfo字典中对象的指针的方式填充请求。虽然我喜欢@ JosephH的解决方案,但我无法弄清楚如何轻松生成依赖树完整的字典或数组。
下面提供了我的自定义NSOperationObject的简化版本;欢迎任何建议。我广泛使用Apple's Concurrency Programming Guide作为参考,但由于我之前没有任何扩展NSOperation课程的经验,我相信有更好的方法可以做到这一点。
#import <Foundation/Foundation.h>
#import "SyncableData.h"
#import "ASIHTTPRequest.h"
@interface PushContentRequest : NSOperation <ASIHTTPRequestDelegate> {
BOOL executing;
BOOL finished;
id <SyncableData> data;
ASIHTTPRequest *request;
NSURL *url;
id <ASIHTTPRequestDelegate> delegate;
}
- (id)initWithDataObject:(id <SyncableData>)theData url:(NSURL *)theUrl delegate:(id <ASIHTTPRequestDelegate>)theDelegate;
@end
#import "PushContentRequest.h"
@implementation PushContentRequest
- (id)initWithDataObject:(id <SyncableData>)theData url:(NSURL *)theUrl delegate:(id <ASIHTTPRequestDelegate>)theDelegate {
if ((self = [super init])) {
executing = NO;
finished = NO;
data = [theData retain];
url = [theUrl retain];
delegate = [theDelegate retain];
}
return self;
}
- (BOOL)isConcurrent {
return YES;
}
- (BOOL)isExecuting {
return executing;
}
- (BOOL)isFinished {
return finished;
}
- (void)start {
if ([self isCancelled]) {
[self willChangeValueForKey:@"isFinished"];
finished = YES;
[self didChangeValueForKey:@"isFinished"];
return;
}
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
request = [ASIHTTPRequest requestWithURL:url];
NSString *xmlToPost = [[NSString alloc] initWithString: [theData getXMLRep]];
[request appendPostData:[xmlToPost dataUsingEncoding:NSUTF8StringEncoding]];
[request setDelegate:self];
NSDictionary *userInfoDict = [[NSDictionary alloc] initWithObjectsAndKeys:data, @"theData", nil];
[request setUserInfo:userInfoDict];
[userInfoDict release];
[xmlToPost release];
[self willChangeValueForKey:@"isExecuting"];
[request start];
executing = YES;
[self didChangeValueForKey:@"isExecuting"];
[pool release];
}
- (void)dealloc {
[delegate release];
[url release];
[data release];
[super dealloc];
}
- (void)requestFinished:(ASIHTTPRequest *)therequest {
[delegate requestFinished:therequest];
[self willChangeValueForKey:@"isFinished"];
[self willChangeValueForKey:@"isExecuting"];
executing = NO;
finished = YES;
[self didChangeValueForKey:@"isExecuting"];
[self didChangeValueForKey:@"isFinished"];
}
- (void)requestFailed:(ASIHTTPRequest *)therequest {
[delegate requestFailed:therequest];
[self willChangeValueForKey:@"isFinished"];
[self willChangeValueForKey:@"isExecuting"];
executing = NO;
finished = YES;
[self didChangeValueForKey:@"isExecuting"];
[self didChangeValueForKey:@"isFinished"];
}
@end
此PushContentRequest的委托当前处理ASIHTTPRequest的UserInfo字典的解释和我的实现中的请求,尽管我认为在PushContentRequest的主体内进行此处理可能更有意义。