[iOS] Grand Central Dispatch (GCD) – dispatch_async

mercredi 2 septembre 2015

Grand Central Dispatch est une technologie développée par Apple pour optimiser la prise en charge des processeurs multi-coeurs, elle se chargera donc de bien distribuer les processus aux différents coeurs.

La fonction dispatch_async permet de créer des threads, processus asynchrone. En faite, elle rajoute le block dans la queue.

Voici un exemple complet:

dispatch_get_current_queue(void);

Cette fonction retourne la queue courante dans lequel le block a été expédié.

 dispatch_get_main_queue(void);

Cette fonction retourne la queue principale ou votre composant UI est en train de s’exécuter.

dispatch_queue_t myQueue = dispatch_queue_create("My Queue",NULL);
dispatch_async(myQueue, ^{
    // Perform long running process
    
    dispatch_async(dispatch_get_main_queue(), ^{
        // Update the UI
        
    });
}); 

Voici un exemple d’utilisation de plusieurs processus pour afficher des images:

NSArray *images = @[@"http://example.com/image1.png",
                 @"http://example.com/image2.png",
                 @"http://example.com/image3.png",
                 @"http://example.com/image4.png"];

dispatch_queue_t imageQueue = dispatch_queue_create("Image Queue",NULL);

for (NSString *urlString in images) {
    dispatch_async(imageQueue, ^{
        
        NSURL *url = [NSURL URLWithString:urlString];
        NSData *imageData = [NSData dataWithContentsOfURL:url];
        UIImage *image = [UIImage imageWithData:imageData];

        NSUInteger imageIndex = [images indexOfObject:urlString];
        UIImageView *imageVIew = (UIImageView *)[self.view viewWithTag:imageIndex];
        
        if (!imageView) return;
        
        dispatch_async(dispatch_get_main_queue(), ^{
            // Update the UI
            [imageVIew setImage:image];
        });
        
    }); 
}
 dispatch_get_global_queue(void);

Si vous souhaitez exécuter une seule opération indépendante en file d’attente (aueue) et que vous n’êtes pas concerné par d’autres opérations simultanées, vous pouvez utiliser la file d’attente concurrente global./p>

dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
    //Background Thread
    dispatch_async(dispatch_get_main_queue(), ^(void){
        //Run UI Updates
    });
});

Le premier appel de fonction permet de créer un nouveau thread et donc exécuter du code qui sera exécuté indépendamment de la suite logique du code. Et le deuxième appel est utilisé pour mettre à jour automatiquement des composants UI qu’on souhaite via threads indépendamment du reste du code.
Par exemple mettre à jour l’affichage d’une progressbar en fonction du temps de download.

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location {
    NSData *data = [NSData dataWithContentsOfURL:location];
    dispatch_async(dispatch_get_main_queue(), ^{
        [self.progressView setHidden:YES];
        [self.imageView setImage:[UIImage imageWithData:data]];
    });
}

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes {
    
}

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
    float progress = (double)totalBytesWritten / (double)totalBytesExpectedToWrite;
    
    dispatch_async(dispatch_get_main_queue(), ^{
        [self.progressView setProgress:progress];
    });
}

Tags: dispatch_async , NSURLSession , progressbar