I'm going to download images and titles from web (probably using AFNetworking) and insert inside UITableViewCell. Since images are not same size I'll need to calculate size for every cell.
Currently in my Post model I have title and imageURL. Should I first download all images, insert in array and then add to cell or should I use that AFNetworking function inside cellForRowAtIndexPath and download images from there?
Since I'm going to need images in both cellForRowAtIndexPath and heightForRow (for calculation), downloading all images first and storing in array might be better solution but dunno if cache is doing all the work so I could go with second approach?
Thanks.
Fot the better performance,
You should approach for the Small sizes of images or few.
downloading all images first and storing in array.
IF the images are huge, then should go for the Asynchronous task to display.
and then Use the custom UIImageView within the cell to show the image.
Related
I'm making a table view that downloads an image for the cell off the web, every time the cell is loaded.
This proves a problem though, as when you scroll down then up again, the cells are reloaded.
Is there any way to stop the unloading of cells, and control how many cells are loaded when the view appears?
I propose that instead of trying to stop your UITableView from reusing cells, which would decrease performance, you store the images you download, using NSCache for example.
NSCache works the same way as a Dictionary - with key value pairs. The main difference however is it incorporates various auto-removal policies, which ensure that it does not use too much of the system’s memory. Here's the documentation on NSCache: https://developer.apple.com/library/ios/documentation/Cocoa/Reference/NSCache_Class/index.html
Using this method: when you're setting up your UITableViewCell, you could check if an image has been downloaded for that NSIndexPath. If an image hasn't been downloaded you download it and add it to the cache once its finished, otherwise you use your cache and get the image from there.
I have tableView with collectionView inside.
I have ~500+ images in collectionView.
Firstly I use paths and load images in collectionView from paths from collectionView:cellForItemAtIndexPath: . But it was slow and I begin to fill collectionView with UIImages from array. It became faster but it must be more faster. How can I accelerate it?
Take a look at FastImageCache, a fast loading image cache. The requirements/assumptions don't fit every use case, but from your problem statement it could work for you.
I have an requirement where I had to load multiple images and videos in the ScrollView
but on iPad 2 my application crashes when I load entire set on one go.It says that application
exits due to heavy memory pressure.
I would like to know how to handle this issue and it it possible to load images one by one when i scroll? and if yes then how it can be done
I think The Best will be to use UITableView instead of scrollView. As tableview uses DEQUEUE so it will do the part of loading/unloading the visible portion of tableview. Table view cell can be customized any way You want.
Hope it will help.
Paging is the way to go.
If you load all the images in the memory then you are compromising scalability in big way for one or two image it will be fine for large number say hundreds it will crash.
One approach is you keep only three images in memory previous image----current image being displayed and ------next image ready for display. And you have to use lazy loading and image caching
Following links will help you
.Icarousel
.AFnetworking's uiimageview category for lazy loading and caching
.ASImageView a light weight uiimageview category if you dont want to integrate full AFNetworking in your project
My app downloads the user's Facebook profile picture with an asynchronous (NSURLConnection) connection so that it can display the profile picture on a customized UITableViewCell. The problem is; the customized tableViewCell is created before the picture gets downloaded so the delay leads to an empty tableViewCell without the picture. How can I solve this problem?
My approach is to reach each cell by using a (for-in enumeration) and (a tag for each cell) in "connectionDidFinishLoading" method.
So guys, what do you think about my approach and do you have any better approaches???
Thanks for your help,
E.
Trying to tag and loop through your cells to find matches won't work because of UITableViewCell reuse. There are only as many cells in memory as you can see on screen, and these cells get recycled to display different data. Therefore, you won't be able to create a tag for each row in your table view, because the table view is only using a handful of cells.
What you should do instead is create a UITableViewCell subclass that knows how to asynchronously download and display in the image itself. Using the UIImageView category from AFNetworking is perfect for doing something like this, instead of having to manage the URL connection yourself. Import this category in your cell subclass, and write a method that calls setImageWithURL: to asynchronously download and display the image. Also, make sure to overload the UITableViewCell method prepareForReuse, in which you should call cancelImageRequestOperation on your image view. This is so the request to download the image is cancelled if the cell is reused before the download is complete.
If we fetch a small image (say, 60 x 60) from the Internet, inside of the method:
-(UITableViewCell *) tableView:(UITableView *) tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath { ... }
What if there are a fixed 25 number of rows vs if the length can be variable (say, 100, or can be 1000)? If we use dequeueReusableCellWithIdentifier to "reuse" a cell, and we probably will need to remove the subviews in this cell (one of which is the 60 x 60 image), and so when the user scroll up and down the list, the cells are reused, and images are re-fetched from the net, and it can be pausing here and there while scrolling.
But if I remove the dequeueReusableCellWithIdentifier and always allocate a new cell:
cell = [[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:TableViewCellIdentifier];
then when I scroll down and up again, the NSLog shows that the images are still being fetched. Is there a way to prevent that, if we don't want to use an array separately to store the fetched images?
(right now, the behavior is, initially, about 7 images are fetched, and if the table is scrolled down 3 rows, then 3 images are fetched, and if the table is scrolled back up 3 rows, then 3 images are fetched again)
you should have an image caching mechanism. download the image if it does not exist. Set an expiration where you will need to refetch it. Then display it.
Next time you load it. you display the already downloaded image and check the expiration. If its expired you download it again, and update the display.
pretty simple.
Only complication is, after the download should the image be over written. I test this with a GUID. When the image download is requested I put a UUID in the tableview or image object itself. I also send that UUID along with the download task. when the download returns you test the download's UUID against the display item's UUID. if they are Equal. then you update the display. if they have changed, then another download was requested and overrode yours. Therefore the images was changed by that process and a download will be finishing soon that does have that UUID and will change the image with its downloaded contents.
Hope that helps :)
You could use image caching as Volure mentioned. I also suggest you implement some form of lazy loading for those images. There are many different implementations for this. This project is a subclass of UIImageView that supports asynchronous loading.
Also, take a look at this question, the answers could be helpful.
hope this helps.
As far as the scroll view pausing your should load your images (if they are not cached or need updating as per DarkAngel's answer) on another thread. I'd use NSOperationQueue.
Here's a good tutorial on setting up NSOperationQueue. A good idea is to use a shared queue in your app delegate that you can just add tasks to when you need it.
Just use SDWebImage or AFNetworking. They both offer a category of UIImageView giving you the caching mechanism.
What that means is if the image downloader library (SDWebImage or AFNetworking) has found an image in its cache, then it will just get that one from disk rather than redownload the image from the web.
You're seeing that lag is most likely because in your cellForRowAtIndexPath: table view delegate method, you're probably downloading the thumbnail image using NSURLConnection on the main thread.
SDWebImage or AFNetworking will essentially do all the hard work for you and make your table responsive. All that you have to do is really:
[myThumbnailImageView imageWithURL:imageURL placeholder:[UIImage imageNamed:#"myPlaceholderImage.png"]];
Once you got that line in there, that's it. Your real image will appear once its downloaded, until then you can continue to smoothly scroll the table view. Each cell will display a placeholder image that you specified (see above line of code) when the image has not been downloaded.
For More convenience to download image use EGOImageLoader/EGOImageView Download this class by this link https://github.com/enormego/EGOImageLoading.
From this EGOCache is used to store your image. First time you download, while scrolling the UITableview get the image from EGOCache store. In that class it store the Downloaded image with key. The key is hashed value of your imageUrl. Use same key to retrieve your image from cache. Tamilarasan