Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Load image to UICollectionView Asynchronously?

How can i load images to a UICollectionview asynchronously? Inside following method?

- (PSTCollectionViewCell *)collectionView:(PSTCollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {

 bookImage = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"%@/%@", docPath, [[preview objectAtIndex:indexPath.row] lastPathComponent]]];
 [[cell grid_image] setImage:bookImage];

}

In viewdidload() i am using following asynch call to load images to "preview "NSMutablearray

 dispatch_queue_t imageLoadQueue = dispatch_queue_create("com.GMM.assamkar", NULL);

dispatch_async(imageLoadQueue, ^{
    //Wait for 5 seconds...
    usleep(1000000);
    docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];


    for(int k=0; k <[allImage count] ;k++){


        imgURL = [allImage objectAtIndex:k];
        [imagePreview addObject:imgURL];
        imgData=[NSData dataWithContentsOfURL:[NSURL URLWithString:imgURL]];


        [imgData writeToFile:[NSString stringWithFormat:@"%@/%@", docPath, [allImage lastPathComponent]] atomically:YES];

    }

    [[self collectionView] reloadData];


});

Please help me..Now its taking too much time for loading...

like image 294
Navi Avatar asked Aug 03 '13 08:08

Navi


People also ask

Does Async image cache?

Unfortunately, at this point, AsyncImage does not cache the images. This means the same image is downloaded again. Let's check out some code: In the code above, loadPhotos uses the async/await feature of Swift to perform and wait for the async tasks.

How do I cache an image in Swift?

Internally, NSURLCache uses both in-memory and on-disk image caching, and it makes its decisions based on the size of the data. All you need to do is to initialise this cache and to set it as a default for your application, and then use NSURLSession to download your images/data.

How do I use SDWebImage in swift 5?

Click File -> Swift Packages -> Add Package Dependency , enter SDWebImage repo's URL. Or you can login Xcode with your GitHub account and just type SDWebImage to search. After select the package, you can choose the dependency type (tagged version, branch or commit). Then Xcode will setup all the stuff for you.

What is Uiimage?

An object that manages image data in your app.


1 Answers

Trying to answer your main question "How can i load images to a UICollectionview asynchronously?"

I would suggest solution offered by "Natasha Murashev" here, which worked nicely for me and it's simple.

If here imgURL = [allImage objectAtIndex:k]; in allImage property you keep array of URLs, then update your collectionView:cellForItemAtIndexPath: method like this:

- (PSTCollectionViewCell *)collectionView:(PSTCollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    NSURL *url = [NSURL URLWithString:[allImage objectAtIndex:indexPath]];

    [self downloadImageWithURL:url completionBlock:^(BOOL succeeded, NSData *data) {
        if (succeeded) {
            cell.grid_image.image = [[UIImage alloc] initWithData:data];
        }
    }];
}

And add method downloadImageWithURL:completionBlock: to your class, which will load images asynchronously and update cells in CollectionView automatically when images are successfully downloaded.

- (void)downloadImageWithURL:(NSURL *)url completionBlock:(void (^)(BOOL succeeded, NSData *data))completionBlock
{
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
        if (!error) {
            completionBlock(YES, data);
        } else {
            completionBlock(NO, nil);
        }
    }];
}

I see you try to preload images before view appears so maybe my solution isn't what you what, but from your question it's hard to say. Any how, you can achieve what you want with this as well.

Swift 2.2 Solution in Swift.

public typealias ImageFetchCompletionClosure = (image: UIImage?, error: NSError?, imageURL: NSURL?) -> Void

extension String {
   func fetchImage(completionHandler: (image: UIImage?, error: NSError?, imageURL: NSURL?) -> Void) {
        if let imageURL = NSURL(string: self) {
            NSURLSession.sharedSession().dataTaskWithURL(imageURL) { data, response, error in
                guard
                    let httpURLResponse = response as? NSHTTPURLResponse where httpURLResponse.statusCode == 200,
                    let mimeType = response?.MIMEType where mimeType.hasPrefix("image"),
                    let data = data where error == nil,
                    let image = UIImage(data: data)
                    else {
                        if error != nil {
                            completionHandler(image: nil, error: error, imageURL: imageURL)
                        }
                        return
                }
                dispatch_sync(dispatch_get_main_queue()) { () -> Void in
                    completionHandler(image: image, error: nil, imageURL: imageURL)
                }
            }.resume()
        }
    }
}

Usage sample:

    "url_string".fetchImage { (image, error, imageURL) in
        // handle different results, either image was downloaded or error received
    }
like image 110
Jonauz Avatar answered Oct 25 '22 14:10

Jonauz