2009-08-20 92 views
18

我想在後臺線程的NSOperation內部做一個Asynchrous NSURLConnection。如何在NSOperation內執行異步NSURLConnection?

(那是因爲我在做對數據的一些非常昂貴的操作,因爲他們回來希望能夠在該數據進來,在後臺)

這是我第一次嘗試:

在我的AppDelegate:

// create the opperation and add it to the queue: 
self.sharedOperationQueue = [[[NSOperationQueue alloc] init] autorelease]; 
LibXMLOperation *op = [[[LibXMLOperation alloc] init] autorelease]; 
[self.sharedOperationQueue addOperation:op]; 

這裏是我的操作:

@interface EbirdLibXMLOperation : NSOperation { 
@private 
    NSURLConnection *urlConnection; 
// Overall state of the parser, used to exit the run loop. 
BOOL done; 
// properties to maintain the NSOperation 
BOOL finished; 
BOOL executing; 
} 
- (void)downloadAndParse:(NSURL *)url; 
- (void)start; 
- (BOOL)isConcurrent; 
- (BOOL)isFinished; 
- (BOOL)isExecuting; 

@property BOOL done; 
@property (nonatomic, retain) NSURLConnection *ebirdConnection; 
// The autorelease pool property is assign because autorelease pools cannot be retained. 
@property (nonatomic, assign) NSAutoreleasePool *downloadAndParsePool; 

@end 


@implementation LibXMLOperation 
@synthesize urlConnection, done; 

- (void)start{ 
    if (![self isCancelled]) { 
    [self willChangeValueForKey:@"isExecuting"]; 
    executing = YES; 
    //set up the thread and kick it off... 
    [[NSURLCache sharedURLCache] removeAllCachedResponses]; 
    NSURL *url = [NSURL URLWithString:@"http://google.com"]; 
    [NSThread detachNewThreadSelector:@selector(downloadAndParse:) toTarget:self withObject:url]; 
    [self didChangeValueForKey:@"isExecuting"]; 
    } else { 
    // If it's already been cancelled, mark the operation as finished. 
    [self willChangeValueForKey:@"isFinished"]; 
    finished = YES; 
    [self didChangeValueForKey:@"isFinished"]; 
    } 
} 

- (BOOL)isConcurrent { 
    return YES; 
} 

- (BOOL)isExecuting { 
    return executing; 
} 

- (BOOL)isFinished { 
    return finished; 
} 


- (void)downloadAndParse:(NSURL *)url { 
    self.downloadAndParsePool = [[NSAutoreleasePool alloc] init]; 
    done = NO; 
    self.characterBuffer = [NSMutableData data]; 
    [[NSURLCache sharedURLCache] removeAllCachedResponses]; 
    NSURLRequest *theRequest = [NSURLRequest requestWithURL:url]; 
    urlConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self]; 
    if (urlConnection != nil) { 
    do { 
     [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; 
    } while (!done); 
    } 
    [self willChangeValueForKey:@"isFinished"]; 
    [self willChangeValueForKey:@"isExecuting"]; 
    finished = YES; 
    executing = NO; 
    // Clean up. 
    self.urlConnection = nil; 
    [downloadAndParsePool release]; 
    NSLog(@"download and parse cleaning up"); 
    self.downloadAndParsePool = nil; 
    [self didChangeValueForKey:@"isExecuting"]; 
    [self didChangeValueForKey:@"isFinished"]; 
} 


#pragma mark NSURLConnection Delegate methods 

// Disable caching so that each time we run this app we are starting with a clean slate. 

- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse { 
    return nil; 
} 

// Forward errors to the delegate. 
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { 
    done = YES; 
} 

// Called when a chunk of data has been downloaded. 
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { 
    // Process the downloaded chunk of data. 
    NSLog(@"Did received %i bytes", [data length]); 
} 

- (void)connectionDidFinishLoading:(NSURLConnection *)connection { 
    // Set the condition which ends the run loop. 
    done = YES; 
}  

@end 

當這個運行時,我看到下面的消息在我的日誌:

2009-08-20 15:18:48.858 App[1001:3e03]*** _NSAutoreleaseNoPool(): Object 0x1126a20 of class NSCFArray autoreleased with no pool in place - just leaking 
Stack: (0x305a2e6f 0x30504682 0x3057deba 0x305ced09 0x30577ddf 0x3056b43e 0x3050764a 0x58fc3 0x3050a79d 0x3050a338 0x94568155 0x94568012) 

此事件發生在最後[自我didChangeValueForKey:@「isFinished」];這向我暗示我正在設置NSOperation錯誤。

任何建議表示讚賞,謝謝。

回答

5

移動行:

[downloadAndParsePool release]; 
self.downloadAndParsePool = nil; 

-downloadAndParse:方法的結束。

+0

好,那很容易。回顧性顯而易見。謝謝。 – 2009-08-20 07:55:08