Ich habe das Problem, wenn ich versuchte, asynchrone Anfragen an den Server von Hintergrund Thread zu tun. Ich habe nie Ergebnisse dieser Anfragen erhalten. Ein einfaches Beispiel, das das Problem zeigt:Asynchrone Anfrage an den Server von Hintergrund Thread
@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
Dann rufe ich dies aus Haupt-Thread
asyncImgRequest = [[AsyncImgRequest alloc] init];
asyncImgRequest.delegate = self;
[self performSelectorInBackground:@selector(downloadImage) withObject:nil];
Methode download ist unten aufgeführt:
-(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];
}
Das Problem ist, dass Verfahren imageDownloadDidFinish nie aufgerufen . Außerdem werden keine der Methoden
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse*)response
genannt. Allerdings, wenn ich ersetzen
[self performSelectorInBackground:@selector(downloadImage) withObject:nil];
von
[self performSelector:@selector(downloadImage) withObject:nil];
alles funktioniert richtig. Ich gehe davon aus, dass der Hintergrund-Thread stirbt, bevor die Async-Anfrage den Job beendet hat und dies das Problem verursacht, aber ich bin mir nicht sicher. Habe ich Recht mit diesen Annahmen? Gibt es eine Möglichkeit, dieses Problem zu vermeiden?
Ich weiß, ich kann sync Anfrage verwenden, um dieses Problem zu vermeiden, aber es ist nur ein einfaches Beispiel, reale Situation ist komplexer.
Vielen Dank im Voraus.
Nach vielen Stunden der Erforschung (8+), wie eine asynchrone NSURLConnection innerhalb eines NSInvocationOperation, keine der Lösungen durchzuführen waren so elegant wie CFRunLoopRun() und CFRunLoopStop(). Das ist VIEL besser, als mit "isExecuting" -Instanzvariablen zu experimentieren, die das KVO-Protokoll verwenden. Zu beachten ist, dass ich @selector (performSelectorOnMainThread: withObject: waitUntilDone: modes :) verwendet habe, indem ich [NSArray arrayWithObject: NSDefaultRunLoopMode] als Modi übergeben habe. Hauptthread zur Erfüllung der UIKit-Anforderungen, NSDefaultRunLoopMode, um die Interaktion der Benutzeroberfläche reibungslos zu halten. Danke vielmals! –
Ich wünschte ich könnte mehr wählen. Das war sehr hilfreich. –
Für Projekte, die mit ARC kompiliert wurden, ist 'NSAutoReleasePool' nicht verfügbar, daher würde der Code wie folgt aussehen: @autoreleasepool {[self downloadImage: urlString]; CFRunLoopRun(); } ' – alokoko