Ho il problema quando ho provato a fare richieste asincrone al server da thread in background. Non ho mai avuto risultati di quelle richieste. semplice esempio che mostra il problema:Richiesta asincrona al server da thread in background
@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
Poi chiamo questo dal thread principale
asyncImgRequest = [[AsyncImgRequest alloc] init];
asyncImgRequest.delegate = self;
[self performSelectorInBackground:@selector(downloadImage) withObject:nil];
metodo downloadImage è riportato di seguito:
-(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];
}
Il problema è che il metodo imageDownloadDidFinish viene mai chiamato . Inoltre nessuno dei metodi
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse*)response
vengono chiamati. Tuttavia, se sostituisco
[self performSelectorInBackground:@selector(downloadImage) withObject:nil];
da
[self performSelector:@selector(downloadImage) withObject:nil];
tutto funziona correttamente. Presumo che il thread in background muoia prima che la richiesta asincrona sia terminata e questo causa il problema, ma non ne sono sicuro. Ho ragione con queste supposizioni? C'è un modo per evitare questo problema?
So che posso utilizzare la richiesta di sincronizzazione per evitare questo problema, ma è solo un semplice esempio, la situazione reale è più complessa.
Grazie in anticipo.
Dopo la ricerca per molte ore (8+) su come eseguire un NSURLConnection asincrono all'interno di un NSInvocationOperation, nessuna delle soluzioni erano elegante come CFRunLoopRun() e CFRunLoopStop(). Questo è MOLTO meglio che scherzare con le variabili di istanza "isExecuting" usando il protocollo KVO. Una cosa da notare è che ho usato @selector (performSelectorOnMainThread: withObject: waitUntilDone: modes :) passando [NSArray arrayWithObject: NSDefaultRunLoopMode] come modalità. Filetto principale per soddisfare i requisiti di UIKit, NSDefaultRunLoopMode per mantenere l'interazione dell'interfaccia utente uniforme. Molte grazie! –
Vorrei poter votare di più. Questo è stato immensamente utile. –
Per i progetti compilati con ARC, 'NSAutoReleasePool' non è disponibile, quindi il codice sarà simile a' @autoreleasepool {[self downloadImage: urlString]; CFRunLoopRun(); } ' – alokoko