处理从依赖于它们的NSOperation对象中的多个NSOperation对象返回的数据

时间:2011-08-16 23:58:54

标签: ios dependencies asihttprequest nsoperation nsoperationqueue

我正在编写一个连接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

2 个答案:

答案 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的主体内进行此处理可能更有意义。