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