2013-06-14 3 views
1

J'écris une application en Objective C et Cocoa pour Mac OS X qui charge des GIF depuis une source externe et les affiche à l'écran. L'utilisateur recherche un terme, les fichiers GIF sont téléchargés et placés dans NSImageViews, puis ces affichages sont affichés dans une vue de défilement.Les GIF ne s'animent pas en utilisant NSThread

Plus tôt, les fichiers GIF ont été animés comme prévu. J'ai alors essayé d'utiliser un NSThread pour faire le chargement des GIF et ajouter à la vue de défilement séparément du fil principal. Voici la méthode qui est appelée dans le fil:

- (void)threading:(id)obj 
{ 

    NSURL *url = [NSURL URLWithString: @"URL HERE"]; 
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; 

    [request setURL:url]; 
    [request setHTTPMethod:@"GET"]; 
    [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; 

    NSError *error; 
    NSURLResponse *response; 
    NSDictionary *data = [NSJSONSerialization JSONObjectWithData:[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error] options:NSJSONReadingMutableLeaves error:nil]; 


    NSArray *gifs = [data objectForKey:@"data"];   


    for (int i = 0; i < 1; i++) { // try to load 1 gif 
     NSString *currentGifURL = @"whatever"; 
     NSImageView *imgView = [[NSImageView alloc] initWithFrame:CGRectMake(10, 1820-100*i, 150, 120)]; 
     // I tried using these 2 lines, still didn't work 
     //[imgView setAnimates:YES]; [imgView setImageScaling:NSScaleNone]; 
     NSURL *imageURL = [NSURL URLWithString:currentGifURL]; 
     NSData *imageData = [NSData dataWithContentsOfURL:imageURL]; 
     NSImage *image = [[NSImage alloc] initWithData:imageData]; 
     imgView.image = image; 
     [_scrollView.documentView addSubview:imgView]; 

    }   
    [_progressIndicator stopAnimation:self]; 
} 

J'appelle plus tard

[NSThread detachNewThreadSelector:@selector(threading:) toTarget:self withObject:nil]; 

Pour créer le fil. Les images apparaissent à l'écran, mais seule la première image est affichée, elles ne sont pas animées. Remplacer littéralement l'initialisation du thread avec le code à l'intérieur du thread rend la même vue, sauf que les GIF sont animés. Y a-t-il quelque chose à propos des threads qui empêcherait les GIF d'animer?

Merci!

+0

AppKit, comme UIKit, n'est fondamentalement pas threadsafe. Le fait que cela fonctionne est un miracle et probablement un bug. – CodaFi

+0

Ah, compris. Puis, question suivante: comment feriez-vous pour charger des images externes sans geler la fenêtre actuelle et faire apparaître la boule de la mort? – user73171

+0

Écrivez une variante de cette méthode qui prend un bloc d'achèvement qui renvoie le tableau d'images que vous avez récupérées sur le thread principal. – CodaFi

Répondre

1

NSImageView n'est pas threadsafe. utiliser - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait

- (void)threading:(id)obj 
{ 

NSURL *url = [NSURL URLWithString: @"URL HERE"]; 
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; 

[request setURL:url]; 
[request setHTTPMethod:@"GET"]; 
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; 

NSError *error; 
NSURLResponse *response; 
NSDictionary *data = [NSJSONSerialization JSONObjectWithData:[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error] options:NSJSONReadingMutableLeaves error:nil]; 


NSArray *gifs = [data objectForKey:@"data"];   


for (int i = 0; i < 1; i++) { // try to load 1 gif 
    NSString *currentGifURL = @"whatever"; 

    // I tried using these 2 lines, still didn't work 
    //[imgView setAnimates:YES]; [imgView setImageScaling:NSScaleNone]; 
    NSURL *imageURL = [NSURL URLWithString:currentGifURL]; 
    NSData *imageData = [NSData dataWithContentsOfURL:imageURL]; 
    NSImage *image = [[NSImage alloc] initWithData:imageData]; 

    [self performSelectorOnMainThread:@selector(LoadImageView:) withObject:image waitUntilDone:NO]; 

}   
    [_progressIndicator stopAnimation:self]; 
} 
-(void)LoadImageView : (NSImage *)image 
{ 
    NSImageView *imgView = [[NSImageView alloc] initWithFrame:CGRectMake(10, 1820-100*i, 150, 120)]; 
    imgView.image = image; 
    [_scrollView.documentView addSubview:imgView]; 
} 
+0

Vous. Sont. A. Lifesaver. Merci beaucoup! – user73171