I have some 50 custom cells in my UITableView. I want to display an image and a label in the cells where I get the images from URLs.
I want to do a lazy load of images so the UI does not freeze up while the images are being loaded. I tried getting the images in separate threads but I have to load each image every time a cell becomes visible again (Otherwise reuse of cells shows old images)
Apps like Facebook load images only for cells currently visible and once the images are loaded, they are not loaded again. Can someone please tell me how to duplicate this behavior.
Thanks.
Edit
Trying to cache images in an NSMutableDictionary object creates problems when the user scrolls fast. I am getting images only when scrolling completely stops and clearing out the cache on memory warning. But the app invariably gets a memory warning (due to size of images being cached) and clears the cache before reloading. If scrolling is very fast, it crashes.
Any other suggestions are welcome
Loading the images on a background thread is still a good idea. If you didn't want to reload them each time, I'd suggest setting up an NSMutableDictionary and storing the images in there. You could use some unique identifier, like the row ID or even the name of the image, as the key for each image.
When loading a cell, you'd send an objectForKey: message to the NSMutableDictionary to retrieve the image for that particular cell (based on your unique key for it). If it returns nil, that means that the image is missing from the cache and you need your background image loading thread to go retrieve it. Otherwise, you will get back the appropriate image for your table cell to display. On a memory warning, you could clear out this cache of images with no adverse effects (aside from forcing them to be reloaded again on demand).
I have just successfully tackled the same problem by using a custom NSOperation to load the images in a queing fasion and stored them into a static NSMutableDictionary as a cache. Below is a link to the basis of the code I used to solve the problem.
Loading remote images for UITableViewCell
Best to read all the threads in the forum to help you understand what's actually going on.
lostInTransit,
I am having a similar problem and while exploring the many different possible solutions I found this blog post:
davidgolightly.blogspot.com/2009/02/asynchronous-image-caching-with-iphone.html
I would also suggest that you download the URLCache sample from the apple developer website:
developer.apple.com/iphone/prerelease/library/samplecode/URLCache/
And here is another post on the problem:
www.markj.net/iphone-asynchronous-table-image/
I'd love you to share your findings as well.
Lazy loading is like synchronous type request.. means wait for respond
ego image button is solution for that..
ego image button is asynchronous type request..don't wait for respond..just display data at a time....
you can download folder from github....
add to your project...
in xib..at image view ,change class to ego image button...
make object of it in m file...
you can use.....
For those who are interested, and are lazy like me, I would like to suggest an open source (MIT license) implementation of lazy/cached network of UIImageView images: SDWebImage
UITableView with image caching and resizing/setting in background thread:
http://blog.slaunchaman.com/2011/08/12/gcd-example-updated-now-with-more-speed/
This is Tutorial about NSOperation with example that show how to Lazy load images in UITableViewCell
Related
Can anybody tell me how to load or set images with high resolutions in UIScrollVIew .
I am getting memory warning and app is getting crashed without any stack trace.
Thank you in advanced.
I was also working on an app which had UIScrollView and had to request for High Resolution Images. The thing is, you should first check the size of the images being downloaded. Lets say, if the image size is more than 10MB, then it would be difficult for your app to survive with such a heavy load.
You can consider the following methodologies.
1.Download your images and compress them.
2.At a particular instance of time, there is no need to populate your Scroll Views array with all the images at once, instead try to have only three images,i.e
1.The current one which is being shown.
2.The previous one.
3.and the image next to the current one.
You can also take help from the link
http://www.raywenderlich.com/10518/how-to-use-uiscrollview-to-scroll-and-zoom-content
You should use the concept of lazy loading. As you said you used UIScrollView that's mean you have lot's of images and I guess you show them one by one or two or three at a time. Load only that images which are visible to the user. One more thing you have to maintain that is when user swipe to next image or next branch of images that's mean next image(s) that's are going to visible to the user. At that time before load the new images release all the previously loaded images from memory. I hope it'll solve your problem.
If you are trying to create multiple UIImageView of high resolution image inside UIScrollView, then it will create memory warning and application will crash.
I will suggest you to try reusable UIImageView , like create 3 UIImageView and replace images in it.
Try circular scrollview.link or UICollectionView
I have a table which is made from custom UITableViewCells which contains downloaded images.
Ive found the app crashes after too many images are displayed. How can best stop this? I don't mind deleting the first images, but don't know of the best way to do it.
EDIT
How do I write the images to the device for caching?
Post your cellForRowAtIndexPath code. Sounds like you have a problem there. If you're certain you do not, then when you receive the memory warning, release any objects you do not need, and can easily be loaded again if required. These objects may be in other ViewControllers not on screen or ImageView objects already displayed.
Best we can do unless you post code.
Or read Apple's Memory Management Guide.
I would like to create a PhotoViewer for an iPhone.
For that, I already created a ScrollView with Paging enabled in that I add programmically add the UIImageViews. The problem I see is, that if I would have like 100 Images and I would all add to the ScrollView it would take alot of performance and memory.
How would you make it more performant? I thought about loading the Images of the following 2 pages and releasing the Images after the 2 Images before when scrolling through the pages.
I thought about creating a Subclass of UIScrollView and to name it UIPhotoScroller (or something like that). But I also want to show a UIView in the MainWindow with Information about the Images. Is it possible to make the UIView visible from the Subclass?
You really would help me with that. Thank you in advance :D
Create an NSCache.
When you need a particular image, try to get it from the cache. If it's not there, load it from disk and save it in the cache. The filename is a suitable key.
When you get a memory warning, tell the cache to empty itself.
The cache will release some of its entries periodically, depending on how it's configured. This is a good thing, but you might want to adjust it to have a particular total memory size. Tweak its parameters until it behaves like you want it to. To see your memory usage, use Instruments.
How about doing a UITableView with a single photo per cell. When a cell is being request by the data source, you display a spinner and have a queued NSOperation load the image and refresh the row when done.
You can control the amount of concurrent ops with a NSQueue, so you have complete control on performace/responsiveness. You can then remove old cached images when low on memory/paging, etc.
There are solutions to horizontal UITableView if you need horizontal scrolling.
Have you looked at the three20 library? There's an example of creating a great Photos app-like viewer of photos, and it's pretty easy to work with the three20 library.
Hope this helps!
I'm having a problem when scrolling down and up a tableView on iPhone it gets kind of stuck while loading the images i need a method to preload the images so the scroll can be fluid or load the images 'till the scroll event stops...
any help on this?
I found this article very helpful. It provides a very detailed example for lazy loading of images in the main runloop.
Lazy Table Images Sample Code included in iPhone Developer Resources. Check out Photo Locations Sample Code as well. It uses Core Data and "lazy loading" techniques if your image files are stored on the device.
Well, generally speaking, preloading images for table view is a bad idea. Think of a following situation: you have 100 cells, each containing one image. That means you'll have to load 100 images before showing the table, which will have a serious impact on avaliable memory.
The "loading effect" you're talking about can be caused by two things:
a) as you have said, the problem with loading images. If so, do it in another thread, and pass the image to main thread when it loads
b) You're using images that are bigger or smaller than the given size. This will result in resizing the image when it appears on screen, causing the ugly stop-effect - the solution is to draw images in size which is exactly the same as their size.
Chope this was helpful, Paul
Not sure about images, but with text I have downloaded JSON files when the view loads, parsed into an array and then loaded the tableview with that array.
I have a table view with all cells having the UITableViewCellStyleSubtitle,
the images of all the cells are got from the server.
However, those images are not changed frequently.
Someone can show me how to improve the user experience? Each time, user scroll down the table, it seems that it goes online to check and download images again.
Or at least, show me some options that are available to achieve the goal.
Thanks,
The Three20 library has an ImageView subclass that accepts a URL to your remote image and uses the excellent TTURLRequest/Caching mechanism to fetch images. It maintains an in-memory and on-disk cache and will only download images if they are not cached or have expired. You can configure the default cache-expiration time or use a value from your HTTP response. If you use the TTTableViewController subclass and the appropriate TTTableItem subclass, you will get the appropriate image downloading behavior for free. However, it is not necessary to use every three component to do what you need. If you're integrating into existing code, you could create your own UITableViewCell subclass that uses a TTImageView instead of the standard UIImageView. Then, in your cell configuration methods, you can set a default placeholder image and a URL to load and it will pretty much take care of the rest. As a performance optimization, you should also implement the UIScrollView delegate methods in your tableview controller to suspend the TTURLRequestQueue during scrolling (take a look at the TTTableViewController to see how this is done).
You could try one of the following
Create an dictionary and cache all the fetched images in it using the image name as the key
Cache and reuse the entire UITableView cells in tableView:cellForRowAtIndexPath:
If it is just one image repeating load it one outside tableView:cellForRowAtIndexPath:
You write that the images change on a monthly basis - you could save the images to disk as they are used and just either check if the images have changed on the back burner or at a given daily interval redownload the images. Brian Chapados reply seems interesting .
Depending on your code there is probably a ton of other ways to improve image loading. Hope that helps...