Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Grand Central Dispatch - display first image when it´s loaded?

I just want to prerender different images for fast access. I use grand central dispatch here to execute the different blocks.

After starting the queue, I want to set the first image when its done. With the current code below, unfortunately the first image will only be displayed when all images has been rendered.

So how can i modify the code? Is it possible to get a delegate when each image has finished?

Here´s the code:

// Async prerendering
    for (int i = 0; i < count; i++) {

        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{

            dispatch_async(dispatch_get_main_queue(), ^{

                UIImage* finalImage = [self prerenderImageForIndex:i];
                [self.imageArray addObject:finalImage];   

                // TODO: i want to display the first image. 
                // rendering goes on in the background 

               if (i==0 && [self.imageArray objectAtIndex:0] != nil ) {
                    self.image = [self.imageArray objectAtIndex:0];
                }
            });
        });
    }

Update:

-(UIImage*) prerenderImageForIndex:(int)frame {
 UIGraphicsBeginImageContextWithOptions(CGSizeMake(self.frame.size.width, self.frame.size.height), NO, 0);      

        for (int i=0; i< [configurationArray count]; i++) {     
         //... get the layerName

        UIImage* layerImage = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:layerName ofType:@"png"]];

              // draw layer with blendmode and alpha 
        [layerImage drawInRect:CGRectMake(x, y, layerImage.size.width, layerImage.size.height) 
                     blendMode:layerblendmode 
                         alpha: layeralpha];

           }   

    // Get current context as an UIImage
    UIImage* finalImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

return finalImage;

}

i just want to know how do i cancel/stop or restart a running queue? Is that possible? Thanks for your help.

like image 553
geforce Avatar asked Oct 08 '22 22:10

geforce


2 Answers

you have to use a serial queue, which executes FIFO for example:

dispatch_queue_t queue;
queue = dispatch_queue_create("myImageQueue", NULL);
for(int i = 0; i<count; i++) {
    dispatch_async(queue, ^{
        // do your stuff in the right order
    });
}

for serial Dispatch queues look at: http://developer.apple.com/library/ios/#documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html

like image 171
Jonathan Cichon Avatar answered Oct 12 '22 11:10

Jonathan Cichon


I'm not sure why you have the dispatch_async calls nested like this but maybe that's the problem. I would imagine something like below would accomplish what you want. You only need to get the main queue when you actually want to do the UI update, everything else should be done on the background queue.

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{

    UIImage* finalImage = [self prerenderImageForIndex:i];
    [self.imageArray addObject:finalImage];

    if (i==0 && [self.imageArray objectAtIndex:0] != nil ) {
        dispatch_async(dispatch_get_main_queue(), ^{   
            self.image = [self.imageArray objectAtIndex:0];
        });
    }
});
like image 40
SteveB Avatar answered Oct 12 '22 10:10

SteveB