我試圖從後臺線程向服務器做異步請求時遇到了問題。我從來沒有得到這些要求的結果。這說明了什麼問題簡單的例子:從後臺線程到服務器的異步請求
@protocol AsyncImgRequestDelegate
-(void) imageDownloadDidFinish:(UIImage*) img;
@end
@interface AsyncImgRequest : NSObject
{
NSMutableData* receivedData;
id<AsyncImgRequestDelegate> delegate;
}
@property (nonatomic,retain) id<AsyncImgRequestDelegate> delegate;
-(void) downloadImage:(NSString*) url ;
@end
@implementation AsyncImgRequest
-(void) downloadImage:(NSString*) url
{
NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:url]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:20.0];
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if (theConnection) {
receivedData=[[NSMutableData data] retain];
} else {
}
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
[delegate imageDownloadDidFinish:[UIImage imageWithData:receivedData]];
[connection release];
[receivedData release];
}
@end
然後我把這種從主線程
asyncImgRequest = [[AsyncImgRequest alloc] init];
asyncImgRequest.delegate = self;
[self performSelectorInBackground:@selector(downloadImage) withObject:nil];
方法downloadImage如下表所示:
-(void) downloadImage
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
[asyncImgRequest downloadImage:@"http://photography.nationalgeographic.com/staticfiles/NGS/Shared/StaticFiles/Photography/Images/POD/l/leopard-namibia-sw.jpg"];
[pool release];
}
的問題是方法imageDownloadDidFinish永遠不會調用。此外,沒有方法
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse*)response
被調用。但是如果我更換
[self performSelectorInBackground:@selector(downloadImage) withObject:nil];
通過
[self performSelector:@selector(downloadImage) withObject:nil];
一切工作正確。我假設後臺線程在異步請求完成之前就已經死了,這導致了問題,但我不確定。我對這個假設是否正確?有什麼辦法可以避免這個問題嗎?
我知道我可以使用同步請求來避免這個問題,但它只是一個簡單的例子,實際情況更復雜。
在此先感謝。
研究關於如何在NSInvocationOperation內執行一個異步NSURLConnection的幾個小時(8個)之後,沒有一個解決方案是像CFRunLoopRun()和CFRunLoopStop()一樣優雅。這比使用KVO協議執行「isExecuting」實例變量要好得多。有一點需要注意的是,我使用@selector(performSelectorOnMainThread:withObject:waitUntilDone:modes :)作爲模式傳遞[NSArray arrayWithObject:NSDefaultRunLoopMode]。主線程滿足UIKit的要求,NSDefaultRunLoopMode保持UI交互的順暢。非常感謝! – 2009-12-19 10:40:49
希望我能投票更多。這非常有幫助。 – 2012-01-24 17:37:09
對於使用ARC編譯的項目,「NSAutoReleasePool」不可用,所以代碼看起來像「@autoreleasepool {[self downloadImage:urlString]; CFRunLoopRun(); }' – alokoko 2012-03-06 21:12:54