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

发布于 2024-11-29 16:30:20 字数 550 浏览 2 评论 0原文

我正在编写一个连接 Web 的应用程序,该应用程序需要执行多个异步请求来加载依赖关系树下部所需的数据。

图 1.


出于可视化目的,请考虑 ASIHTTPRequests A、B、C、D、E 和 F 的示例:

A 的 url 取决于 B 和 C 的结果,

B 的 url 取决于结果D、E 和 F 的值。B

和 C 可以同时计算,D、E 和 F 也可以同时计算。

NSOperationQueue = [(D,E,F),(B,C),A]


到目前为止,我有创建了一个NSOperationQueue 包含 ASIHTTPRequest 的依赖树。然而,ASIHTTPRequests 的 URL 应该依赖于之前操作的结果,但现在它们并不依赖于。

问题:将多个 NSOperation 执行的计算结果传递给依赖于它们的 NSOperation 的最佳方法是什么,以及如何使用 ASIHTTPRequests 进行设置?

提前致谢, 朱利安·塞佩克

I am writing a web-connected application that needs to execute several asynchronous requests to load data needed lower down in the dependency tree.

Fig 1.


For visualization purposes, consider an example with ASIHTTPRequests A,B,C,D,E, and F:

A's url depends on the result of B and C,

and B's url depends on the result of D, E, and F.

B and C can be computed concurrently, and so can D, E, and F.

NSOperationQueue = [(D,E,F),(B,C),A]


Thus far, I have created an NSOperationQueue that contains a dependency tree of ASIHTTPRequests. However, the URLs of the ASIHTTPRequests should depend on the results of the previous operations, and, right now, they do not.

The question: What is the best way to pass the results of the computations performed by multiple NSOperations to the NSOperation that depends on them, and how can I set this up with ASIHTTPRequests?

Thanks in advance,
Julian Ceipek

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

从来不烧饼 2024-12-06 16:30:20

我会做以下事情。

首先,队列:

D、E、F 和 C

在 D、E 和 C 的 requestFinished 委托回调中F,检查其他所有3个请求是否已完成,如果是则发送B。

对B和B的回调执行相同的操作C - 如果它们都完成了,则发送 A。

您需要某种由所有请求共享的对象来存储早期请求的结果/状态。

I would do the following.

To start with, queue:

D, E, F and C

In the requestFinished delegate callback for D, E & F, check if the other all 3 requests have finished, if so send B.

Do the same for the callbacks for B & C - if they've both finished, send A.

You'd need some kind of object that's shared by all requests to store the results / status of earlier requests into.

芯好空 2024-12-06 16:30:20

我最终通过将 ASIHTTPRequest 包装在自定义 NSOperation 对象中来解决此问题,该对象以自定义请求 B 包含指向 D、E 和 F 的 ASIHTTPRequest UserInfo 字典中对象的指针的方式填充请求。虽然我喜欢 @JosephH 的解决方案,但我无法弄清楚如何轻松生成具有完整依赖关系树的字典或数组。

下面提供了我的自定义 NSOperationObject 的简化版本;欢迎任何建议。我使用了 Apple 的并发编程指南 广泛作为参考,但因为我之前没有任何扩展 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 的主体中进行此处理可能更有意义。

I ended up solving this problem by wrapping the ASIHTTPRequest in a custom NSOperation object that populated the request in such a way that custom request B contained a pointer to an object in D, E, and F's ASIHTTPRequest UserInfo Dictionary. While I liked @JosephH's solution, I couldn't figure out how to easily generate a dictionary or array with dependency tree intact.

A simplified version of my custom NSOperationObject is provided below; any suggestions are welcome. I used Apple's Concurrency Programming Guide extensively as a reference, but as I have not had any prior experience extending the NSOperation class, I am sure that there is a better way to do this.

#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

The delegate of this PushContentRequest currently handles the interpretation of the ASIHTTPRequest's UserInfo Dictionary and the request in my implementation, though I suppose that it might make more sense to do this processing within the PushContentRequest's body.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文