Loading multiple images in background thread in iOS - ios

I am creating an iphone app, where I am trying to fetch multiple (5-7) hi-res images from backend server using URL. All fetched images I need to set in a slideshow, now the problem is that very first time if I am fetching images from server then my images are not displaying. Instead of images, am getting white background. Again if I go back and fetching the same images then it's displaying correctly.
Here is my code :
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
for (int i=0; i<[end.slideShowArray count]; i++) {
SlideShow *pro = [[SlideShow alloc] init];
pro = [end.slideShowArray objectAtIndex:i];
NSURL *url = [NSURL URLWithString:pro.imageUrl];
NSData *imageData = [NSData dataWithContentsOfURL:url];
UIImage *img = [UIImage imageWithData:imageData];
dispatch_async (dispatch_get_main_queue (),
^{
[slideshow addImage:img];
});
}
});

You're creating a new SlideShow every time around the loop. I think you intended to create a single slide show then add all the images to it.

Related

how to create own custom listener in iOS?

I have two views on which images are loading from server.Images are loaded asynchronously.So when loading of images is done i want to call a function or execute a block of code.So how can i create a listener which listen to loading of images. I have three images on view for loading of each image I am using below code to load images from server.
dispatch_async(queue, ^{
NSString *urlString=[IMAGE_BASE_URL stringByAppendingString:bc.logo];
NSLog(#"logo url is %#",urlString);
NSURL *logo_url = [NSURL URLWithString:urlString];
NSData *logo_image_data= [NSData dataWithContentsOfURL:logo_url];
UIImage *logo_imge= [UIImage imageWithData:logo_image_data];
dispatch_async(dispatch_get_main_queue(), ^{
self.img_front_logo.image = logo_imge;
});
});
I want to get notification in my class when loading of all three images is done not for single image.
I am beginner in iOS so don't have any idea about this?
Please use this code
AsyncImageView *asyncimage = [[AsyncImageView alloc]initWithFrame:CGRectMake(4,4,146,146)];
NSString *urlString=[IMAGE_BASE_URL stringByAppendingString:bc.logo];
asyncimage.imageURL=[NSURL URLWithString:urlString];
[backviewright addSubview:asyncimage];

How to asynchronously download files in a specific order in iOS?

My iPhone app makes a asynchronous request with NSURLRequest to my site.
The response is JSON with 10 URLs to images. When I receive the asynchronous response I want to download the 10 files using a loop, creating an NSMutableArray of UIImage objects.
I tried to do this with the method NSData dataWithContentsOfURL, and it works but isn't asynchronous, so the user interface is blocked.
If I try to use the NSURL asynchronous method inside the response of this asynchronous method, when I receive the 10 responses with the images, I can't know if the images have been downloaded in order, and in my application the order is important.
What is a solution for downloading files in order, without blocking the UI?
My code:
// Create the request.
NSString *advertURL = [NSString stringWithFormat: #"http://www.myURL"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:advertURL]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
// Create url connection and fire request
imagesConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
When I receive response:
//decode json with the urls
NSArray* json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
//star the loop to downloading the ten images
for (int i=0; i<10; i++) {
//find image[i] url from json
NSString *fullImage_URL = json[i][#"url"];
//download image synchronously (this blocks the UI!!)
NSData * data = [NSData dataWithContentsOfURL:[NSURL URLWithString:fullImage_URL]];
//insert image in the array
arrayImages[i] = [UIImage imageWithData:data];
}
Then, when I'm sure the array has 10 images and they're in order, I can start to show images on the screen.
Instead of processing the JSON array and then looping and fetching all those images on the main thread, why not do it on a background thread. In the background, run the loop, and at the end, call another method on the main to signal the completed task.
//star the loop to downloading the ten images ... in the background
dispatch_queue_t currentQueue = dispatch_get_current_queue();
dispatch_retain(currentQueue);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0, ^(void) {
for (int i=0; i<10; i++) {
//find image[i] url from json
NSString *fullImage_URL = json[i][#"url"];
//download image synchronously (this blocks the UI!!)
NSData * data = [NSData dataWithContentsOfURL:[NSURL URLWithString:fullImage_URL]];
//insert image in the array
arrayImages[i] = [UIImage imageWithData:data];
}
// Return to main queue
dispatch_async(currentQueue, ^{
// process arrayImages now
});
dispatch_release(currentQueue);
});
To read more about the dispatch queues, check this out:
https://developer.apple.com/library/ios/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html#//apple_ref/doc/uid/TP40008091-CH102-SW1
There are many other ways to do this. Personally, I'm a fan of using NSNotificationCenter myself, and the OBSERVER pattern.
https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/Reference/Reference.html

ALAssetRepresentation fullScreenImage

I have a ALAssetRepresentation question. There is a table which displays gallery images in high resolution. The fullScreenImage method takes too much time and the table works slowly. How can I implement a faster loading? For example, gallery images loading occurs immediately in the https://itunes.apple.com/us/app/print-studio-print-photos/id601882801?mt=8, how could they have done this?
ALAsset *result = photos[_index];
UIImageView *photoView = (UIImageView*)[contentView viewWithTag:PHOTO_VIEW];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
ALAssetRepresentation *represintation = [result defaultRepresentation];
NSURL* aURL = represintation.url;
[library assetForURL:aURL resultBlock:^(ALAsset *asset){
UIImage *copyOfOriginalImage = [UIImage imageWithCGImage:[[asset defaultRepresentation] fullScreenImage] scale:0.3 orientation:UIImageOrientationUp];
copyOfOriginalImage = [copyOfOriginalImage imageByScalingAndCroppingForSize:CGSizeMake(600, 600)];
dispatch_async(dispatch_get_main_queue(), ^{
[photoView setImage:newImg];
[photoView setNeedsDisplay];
});
}
failureBlock:nil];
});
You can preload images before they are scrolled onto screen. The images you are preloading can be done on a background thread and saved into an NSCache instance. The cache will automatically purge (if you set the countLimit or the device runs low on memory) so when you preload, check for an item in the cache and load on a background thread if required.

Loading image in to UIImageView in dispatch not working

I'm working with a UICollectionView and I need to load images in to the collection cell.
Here is the code
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(queue, ^{
NSURL *imageURL = [NSURL URLWithString:post.cover_img_url];
NSData *data = [NSData dataWithContentsOfURL:imageURL];
UIImage *image = [UIImage imageWithData:data];
dispatch_async(dispatch_get_main_queue(), ^{
[cell.cover_img setImage:image];
});
});
post.cover_img_url = the_url_for_the_image;
cell.cover_img = the_UIImageView_object;
When I set the image not from the web, it works perfectly.
But when I try from the web, the UIImageView is blank not image.
Anyone have any ideas?
Your code looks like it should be working, but there are a couple of things that you need to test. First, you need to check to make sure that imageURL is both non-nil, and points to exactly where you think it's pointing. Copy paste a log result to your desktop browser if you have to.
NSLog(#"%#",imageURL);
Second, in the event that fetching the image fails, you need to be able to detect this. I recommend that if you continue to use the dataWithContentsOfURL: route that you at least use the following to check the error:
NSError *error = NULL;
NSData *data = [NSData dataWithContentsOfURL:imageURL options:NSDataReadingMappedIfSafe error:&error];
if (error) {
// ...
}

iPhone app flipbook animation crashing on device

The app uses a series of jpg's and a timer that steps through them to make an animation.
During the animation on the device, it crashes (didReceiveMemoryWarningError.)
I'm new to iPhone programming and Objective-C. How can I optimize this flipbook for the iPhone?
I can imagine simply compressing the jpeg's and perhaps losing some quality would help, but my understanding is the iPhone does its own image compression/decompression on the device and I may be wasting my time.
Tried different things, eventually hit on storing an array of NSData objects and converting to UIImage on the fly.
for (NSString *imageFile in directoryList) {
NSString *fileLocation = [imageFolder stringByAppendingPathComponent:imageFile];
NSData *imageData = [NSData dataWithContentsOfFile:fileLocation];
if (imageData) {
[images addObject:imageData];
} else {
[Util trace:#"cannot get image data for image named: %#", fileLocation];
}
and then to update your image:
-(void)updateImageView:(id)sender
{
UIImage *anImage = [UIImage imageWithData:[images safeObjectAtIndex:nextImage] ];
[imageView setImage:anImage];
nextImage++;
}

Resources