Updating Tableview with photos in the background - ios

I'm currently hitting an API to get a list of inventory items. Right now I am also downloading all of the photos for all of the items on initial load. What I want to do is load the table view with all of the text (be able to interact with the tableview) and then load the photos in the background and update each row once the photo has been retrieved so that it loads faster. I have all of the URLs of the photos from the API. How would I do this?

I am using Alamofire Image for this purpose. Here is a sample code.
After installing its pod, you can do:
cell.yourImageView.af_setImageWithURL(url, placeholderImage: nil, filter: nil, imageTransition: .CrossDissolve(0.5), runImageTransitionIfCached: false, completion: {response in
// if you have activity indicator you can stop it when images is downloaded
//cell.activityIdicator.stopAnimating()
})

There are many sdk available for lazyloading. You can use SDWebImage for same.
It will automatically load image into your UIImageView as soon as image download.

Related

Share full-size image from remote URL

I found this tutorial in order to let my users share images from my app:
https://www.hackingwithswift.com/articles/118/uiactivityviewcontroller-by-example
Here is the relevant code:
let items = [yourImage]
let ac = UIActivityViewController(activityItems: items, applicationActivities: nil)
present(ac, animated: true)
It looks like I need to pass a UIImage in the items array.
In my app, I show a feed of images. In the API call for the feed, each image has a thumbnail URL (smaller size) and a full-size URL. My app displays the thumbnail images in the feed in order to keep my app speedy.
This activity view controller is triggered when the user long-presses one of the images in the feed. The problem is that I want the user to be able to share the full-size image (which isn't loaded into any ImageView in the feed), instead of the thumbnail image.
How can I do this?
I've considered fetching the full-size image on long press by following this tutorial, but this causes issues in that the activity view controller doesn't actually show until the image is fully downloaded.
What else can I do??
As an additional question, would the same apply to if I wanted to let the user share a video (mp4)?

Unable to setup images from JSON?

I'm using Firebase Database & Firebase Storage. I have an iOS Swift app, that allows the user to select multiple images, upload them to Firebase Storage, after the upload, it gets the downloaded URLs and stores them like:
In order to display those images in the app, I have the following xib file:
Where the middle (big) UIImageView is inside of a UIStackView because it could display more than 1 image.
My problem is that I get the URLs from the database, but for some reason I'm not able to display them in the app. I use the framework SDWebImage for caching and displaying images. So far in the app, it worked fine, but not here. I don't get where I'm wrong.
if let photoURLString = post?.photoURLs
{
for photo in photoURLString
{
let photoURL = URL(string: photo)
print(photoURL!)
postImage.sd_setImage(with: photoURL)
//postImagesStackView.addArrangedSubview(postImage)
}
}
post is the model object. I'm using for in to loop through the array of images from the database. When I print each url, I get the actual URL. But it's simple not displayed. I get this. The images are nowhere to be found/displayed:
Try to add aspect ratio for UIImage. Ex: In xib file, set ratio of UIImage to 1.

SDWebImage starts to load too late

In my cellForRowAtIndexPath, I am using the following function inside dequeResuableCell to update the image in the cell
let imageNSURL = NSURL(string: post.imageUrl)
let placeHolderImage = UIImage(named: "LoadingPlaceHolder")!
postImageView.sd_setImageWithURL(imageNSURL, placeholderImage: placeHolderImage, options: [], progress: { (byteSent: Int, byteExpectedToSend: Int) in
// Progress
}, completed: { (image: UIImage!, error: NSError!, imageCacheType: SDImageCacheType, url: NSURL!) in
if error != nil {
print("Error \(error.localizedDescription)")
} else {
// Image Download Complete
}
})
However, every time the cell is "just about to appear", I see a glimpse of the placeHolder image. It seems like the SDWebImage SDK only starts downloading the image close to when the cell actually appears on the screen. I was wondering if anyone else is experiencing this or knows how it could be fixed?
----Update----
In response to the comments
I thought cellForRowAtIndexPath is called way ahead of cell being actually displayed (2,3 cells?). willDisplayCell is the one that is displayed just before the cell is shown. But I guess Im wrong as what you said made sense. I was't scrolling very fast and the file is only 55kb. Caching the image works but that is only after the image gets downloaded. What I want to achieve is that the image gets downloaded maybe 2,3 cells earlier so that it is ready in the cache for the cell to be loaded.
What you are seeing is probably network latency.
Depending on the cache state of the url you are loading, SDWebImage will probably be downloading the image from a remote server and depending on the size and network type this could take a few moments.
You aren't trying to load the image until the cell is dequeued, this only happens moments before the cell is displayed. You probably want to look at something like SDWebImagePrefetcher. This would allow you to cache the images at an earlier stage in your app lifecycle and should (in most cases) ensure the images are available locally prior to showing the cell eliminating network latency.

PINRemoteImage delete cache

I'm using PINRemoteImage in my iOS App for setting image on UIImageView. I always have the same link for image, but in meantime image can change (I can upload different image), but whenever I call pin_setImageFromURL on UIImageView it always sets an old image (not if I delete app and reinstall it). I found out that calling [[[PINRemoteImageManager sharedImageManager] defaultImageCache] removeAllObjects] will delete image from cache but only when I close and reopen app, so does anyone known how to force app to update cache immediately after calling upper method?
I discovered this method to clear cache:
[[[PINRemoteImageManager sharedImageManager] cache] removeObjectForKey:
[[PINRemoteImageManager sharedImageManager]cacheKeyForURL:your_URL processorKey:nil]];
So, in your - (void)viewWillAppear:(BOOL)animated you can set again your ImageView with your_URL.
That did the trick at my side ;)
A simple solution in Swift for removing image from cache is:
import PINRemoteImage
import PINCache
if let cacheKey = PINRemoteImageManager.sharedImageManager().cacheKeyForURL(NSURL(string: "http://your-image-url"), processorKey: nil) {
PINRemoteImageManager.sharedImageManager().cache.removeObjectForKey(cacheKey, block: nil)
}

SDWebImageCache precaching images

I'm using the SDWebImage plugin and I have run into the following scenario: I have two UIViewController's A and B. In UIViewControllerB I am loading a series of 10 - 15 images from the web in a UIImageView with the following code:
UIImageView *imageView = [[UIImageView alloc] init];
[imageView sd_setImageWithURL:[NSURL URLWithString:[sourceDictionary objectForKey:#"image"]]
placeholderImage:[UIImage imageNamed:#"placeholder"]];
This works well. Except that I begin downloading these images once the user loads UIViewControllerB. I was wondering if there was a way from me to begin to pre-cache or begin downloading these images while the user is still on UIViewControllerA so that when the user gets to UIViewControllerB they see a shorter delay? How would I do this in a manner so that the image isnt downloaded twice if the user switches to the second viewcontroller while a download is taking place?
Possible workaround could be to implement custom download manager using Singleton pattern, so it's available from both A and B.
Then you can track the list of image URLs requested to be downloaded as well as completed handlers to be called when download completed.
First you check that the download of the image with same URL is not taking place already and then either add image into the list and completed handler or just add new handler. You can use dictionary as a storage, using URL as a key.
Then you can use SDWebImageManager with downloadImageWithURL method, where on completed method you remove image from the list and trigger corresponding completed handlers.
So at B you know that the download has been finished. You do not necessary need to cache images manually with SDWebImageCache, let SDWebImage to do it for you automatically, so when your on completed method get called just do the same as you do, but since image has been already downloaded SDWebImage will take it from the cache. Alternatively you can send back UIImage downloaded into the completed handler.

Resources