NSOperations之间的数据传输

我想获得以下内容:我在NSOperationQueue中有两个NSOperations。 首先是从网站下载(获取一些json数据),下一个是解析该数据。 这是依赖性操作。 我不明白如何将它们连接在一起。 如果它们都被分配并且在队列中,那么如何将json字符串转换为解析它的操作? 如果这个队列在另一个NSOperationQueue内执行一个由前面提到的两个NSOperation组成的NSOperation,那么这是一个问题吗?

我所能找到的只是将数据传输给主线程(performSelectorOnMainThread)上的委托,但我需要在后台执行所有这些操作。

谢谢。 代码:NSDownload:NSOperation

    - (instancetype)initWithURLString:(NSString *)urlString andDelegate:(id<JSONDataDelegate>)delegate
{
    self = [super init];
    if (self) {
        _urlStr = urlString;
        _delegate = delegate; /// this needs to be a NSOPeration
        _receivedData = [NSMutableData dataWithCapacity:256];
    }
    return self;
}

#pragma mark - OVERRIDE

    - (void)main
    {
        @autoreleasepool {

            if (self.isCancelled) {
                return;
            }

            NSURL *url = [NSURL URLWithString:self.urlStr];
            NSURLRequest *request = [NSURLRequest requestWithURL:url];
            self.urlConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
        }
    }

    #pragma mark - NSURLConnectionDataDelegate

    - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
    {
        if (self.isCancelled) {
            [connection cancel];
            self.receivedData = nil;
            return;
        }
        [self.receivedData appendData:data];
    }

    - (void)connectionDidFinishLoading:(NSURLConnection *)connection
    {
        if (self.isCancelled) {
            self.receivedData = nil;
            return;
        }
        // return data to the delegate
        NSDictionary *responseDict = @{JSON_REQUESTED_URL : self.urlStr,
                                       JSON_RECEIVED_RESPONSE : self.receivedData};
        [(NSObject *)self.delegate performSelectorOnMainThread:@selector(didReceiveJSONResponse:) withObject:responseDict waitUntilDone:NO]; // ok to uses performSelector as this data is not for use on the main thread ???
    }

    - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
    {
        // return error to the delegate
        [(NSObject *)self.delegate performSelectorOnMainThread:@selector(didFailToReceiveDataWithError:) withObject:error waitUntilDone:NO];
    }

@ user1028028:

使用以下方法。

1)维护您用于添加DownloadOperation的操作队列引用。

2)在connectionDidFinishLoading方法中,创建ParseOperation实例,设置json数据并将其添加到操作队列中。 在DownloadOperation中维护ParseOperation强引用变量,并通过DownloadOperation接口处理取消解析操作。

3)完成解析后,调用主线程中的UI功能。

我希望这有帮助。


正如lucianomarisi所指出的那样,通常最好是让第一个操作生成第二个操作。 这通常更容易管理。 操作依赖关系在我的经验中并不常见。

也就是说,当然可以在操作之间传递数据。 例如,你可以在第二个操作中创建一个datasource属性。 那将是要求其数据的对象; 该对象将是第一个操作。 不过,这种方法可能需要锁定。

您也可以在第一个操作中创建nextOp属性。 完成后,它会在退出之前在第二个操作中调用setData: 你可能不需要为此锁定,但你可能会。 在大多数情况下,第一次操作在此时安排nextOp会更好(这又是lucianomarisi的答案)。

关键是操作只是一个对象。 它可以有任何你想要的方法和属性。 你可以将一个操作传递给另一个操作。

请记住,由于一个操作在后台运行,所以没有理由需要使用NSURLConnection的异步接口。 同步API( sendSynchronousRequest:returningResponse:error:对此很好,并且更容易编写代码,甚至可以使用一个简单的NSBlockOperation 。或者,您可以使用异步NSURLConnection接口,但实际上不需要NSOperation

我还注意到:

    _receivedData = [NSMutableData dataWithCapacity:256];

它真的是一小段JSON数据吗? 很难相信这种复杂性是值得的,将这样一个小的解析操作转移到后台。

(作为一个方面说明,除非你确切地知道内存的大小,手动指定容量通常没有多大好处,尽管这并不总是清楚这是一个好处,我相信NSURLConnection现在使用的是调度数据,所以你实际上要求一个永远不会被使用的内存块,当然Cocoa也不会分配它,因为它优化了那个......重点在于你可能只是使用[NSMutableData data] 。明智的关于这些事情;你通常只能妨碍它的优化。)


正如罗布所说,除非您有任何特别的理由使用操作,否则请使用同步调用。 然后在MainThread或您需要的任何其他线程上执行选择器。 除非你想在单独的操作或线程(明确)中分开检索和解析。

以下是我用于json检索和解析的代码:

-(BOOL) loadWithURL:(NSString*) url params: (NSDictionary*) params andOutElements:(NSDictionary*) jElements

{

NSError *reqError = nil;
NSString* urlStr = @"";//@"http://";
urlStr = [urlStr stringByAppendingString:url];

NSURL* nsURL = [NSURL URLWithString:urlStr];

//Private API to bypass certificate ERROR Use only for DEBUG
//[NSURLRequest setAllowsAnyHTTPSCertificate:YES forHost:[nsURL host]];


NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL: nsURL
                                                       cachePolicy:NSURLRequestUseProtocolCachePolicy
                                                   timeoutInterval:60.0];

[request setHTTPMethod:@"POST"];
NSString *postString = @"";
if(params!=nil) {
    NSEnumerator* enumerator = params.keyEnumerator;
    NSString* aKey = nil;
    while ( (aKey = [enumerator nextObject]) != nil) {
        NSString* value = [params objectForKey:aKey];

        //Use our own encoded implementation instead of above Apple one due to failing to encode '&'
        NSString* escapedUrlString =[value stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
        //Required to Fix Apple bug with not encoding the '&' to %26
        escapedUrlString =  [escapedUrlString stringByReplacingOccurrencesOfString: @"&" withString:@"%26"];

        //this is custom append method. Please implement it for you -> the result should be 'key=value' or '&keyNotFirst=value'
        postString = [self appendCGIPairs:postString key:aKey value:escapedUrlString isFirst:false];
    }
}


//************** Use custom enconding instead !!!! Error !!!!! **************
[request setHTTPBody:[postString dataUsingEncoding:NSUTF8StringEncoding]];


NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&reqError];
if(reqError!=nil) {
    NSLog(@"SP Error %@", reqError);
    return NO;
}

NSString *json_string = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
//Handles Server Errors during execution of the web service that handles the call.
if([json_string hasPrefix:@"ERROR"] == YES){
    NSLog(@"SP Error %@", lastError);
    return NO;
}

//Very Careful!!!!!! Will stop for any reason.!!!!!!
//Handles errors from IIS Server that serves teh request.
NSRange range = [json_string rangeOfString:@"Runtime Error"];
if(range.location != NSNotFound) {
    NSLog(@"SP Error %@", lastError);
    return NO;
}

//Do the parsing
jElements = [[parser objectWithString:json_string error:nil] copy];
if([parser error] == nil) {
    NSLog(@"Parsing completed");
} else {
    jElements = nil;
    NSLog(@"Json Parser error: %@", parser.error);
    NSLog(@"Json string: %@", json_string);
    return NO;
}

//Parsed JSON will be on jElements
return YES;

}

链接地址: http://www.djcxy.com/p/65127.html

上一篇: Data transfer between NSOperations

下一篇: NSOperation remains in an NSOperationQueue after cancellation