For the slideshow feature, the images are on a remote server, then can we implement a batch look ahead download of the images? We want say 'n' images ahead downloaded when an image is being viewed - this helps in providing a smoother viewing experience. Is this a good way to get zero latency for the slideshow or is there any better way than this.
To provide a smooth viewing experience as well as reduce (not zeroing) the latency for your slide show, I agree with caching mechanism.
I assume that you have a list of image urls, now as soon as the slide show displaying on the screen, start loading visible items. Trigger scroll view did scroll and load in the background the next n images after the last visible index, then cache them. So that whenever user scrolling to next indexes, images almost the time will be there in your memory and displayed instantly.
Why we should trigger scroll view did scroll. Firstly, because that is the idle time that allows you start doing things without user's notice. Secondly, if you start loading images while scrolling, at the time it is set to UIImageView, your slide show will be lag due to that task executed on main thread.
As the answer above, SDWebImage is a good library that can help you finish your task.
By the way, if you will consider of using SDWebImage, I would suggest you config this option
/**
* By default, image downloads are started during UI interactions, this flags disable this feature,
* leading to delayed download on UIScrollView deceleration for instance.
*/
SDWebImageLowPriority = 1 << 1,
I hope my answer will contribute 2 cents to solve your problem.
In my opninion, use SDWebImage https://github.com/rs/SDWebImage to preload images and clean memory cache if if exceed memory-limit.
Related
In my app, I have a UITableView which displays fairly large images and loads a moderately designed Xib file to display it in. Each image is around 700KB to 1MB in size. The flow is virtually never ending, it loads more and more as we scroll down. So you can imagine that I am running into memory issues.
I have tried using SDImageCache and NSCache. The former used disk memory for caching images. In both cases, the caches somehow didn't clear images automatically. I had to manually clear them when I got a Received memory warning prompt. And each time I clear these caches, the memory freed seems to be lesser each subsequent time.
Now I confused as to which cache strategy I must use for such a long list of images. Might I be having some leaks somewhere? They certainly didn't show up when I profiled the app.
P.S.: I am loading the images from the web. Just to be clear.
From the docs:
UIImage
+(UIImage *)imageNamed:(NSString *)name
Discussion This method looks in the system caches for an image object
with the specified name and returns that object if it exists. If a
matching image object is not already in the cache, this method loads
the image data from the specified file, caches it, and then returns
the resulting object.
So I guess leaving this to the UIImage class is a good approach.
Hope this helps!
As we implemented it in both Android and iOS: once you can show on the screen only 2-3 images.
Load in memory 2 more for the downwards scroll and 2 more for the upwards one. So you have in memory 7 images. Display them. The other images must be stored in files (when you download them). If the user scrolls too fast, do not show all the sequence of the images, instead show some "loading" icons in place of the images. When the scrolling stops, show the appropriate image + the previous one + the next one + prepare 2 more (for upwards scroll) and 2 more for downwards scroll.
I'm building an application that requires a bunch of local images to be displayed in the imageview of a uitableviewcell. However, i'm having difficulty optimizing the performance of the uitableview. I've noticed two issues specifically: first, the view takes a while to load. Second, the scrolling gets laggy when new cells are displayed.
The viewDidLoad is loading in the images like this:
for (Object *object in self.objects)
{
object.thumbnail = [UIImage imageNamed:object.imageName];
}
this is obviously causing the long-load issue, but I'm not sure how else to get those images loaded. Is it a size issue? is this just a bad way of doing it?
The process of displaying the images also seems to be problematic, in other words, even after the images have been assigned to the thumbnail property, they still take too long to be drawn.
Although this is a specific case, I'm curious more generally on how apple loads images in photos so efficiently. Any insights? thanks
Whenever I find that my UI is lagging, the first thing I suspect is that I am performing some operation synchronously (on the main thread) that should be performed asynchronously (on a background thread).
I am also very curious as to how exactly Apple is achieving that performance in the photo app. I am writing an app that has similar requirements as yours right now. My current approach is to load a bunch of photos from disk into memory asynchronously as soon as the user opens my view controller, and continue to load (and remove photos) from memory - ahead of time - as the user scrolls.
Currently, I load each photo from disk asynchronously in cell for row at index path, which is pretty fast, but causes this cascading effect to happen if you scroll quickly through the table view. That is, the cell will appear empty for a moment before the photo appears.
I hope this sheds some light for you.
You may also be interested in trying SDWebImage - which includes an image cache object that has been making my life easier when dealing with local photos.
They are doing everything in the background on various detached threads most likely. This will allow for a great deal of fluidity in applications that are hosting/presenting a great deal of information. I have created a photo gallery myself in various applications, loading many photos simultaneously from different web APIs and whatnot, and by simply creating new threads and managing the allocation efficiently and accurately, you can get a very smooth interface/interaction
Well, the long-load issue is caused by this part of your code - UIImage imageNamed:, because this method caches all the images on the same thread, and also could crash the app if the memory is overloaded.
Try looking at this library - it should do what you are trying to achieve :)
http://www.cocoacontrols.com/platforms/ios/controls/ktphotobrowser
TL:DR
What technique does Apple use to make Photo.app so fast, even with large images?
Long Version
I watched Apple's WWDC 2010 video about scroll views to learn how to replicate Photo.app pagination behavior and low memory utilization (PhotoScroller Demo). It works well, but since images are loaded only when they are needed, when I try to paginate to another image, the app locks while the JPEG is being decompressed.
The same video shows a tiling technique to get better performance, but since I'm using photos taken from the camera and stored in the app, that doesn't seem feasible (having multiple copies of each photo, in different resolutions, would consume too much space - 4MB vs 27MB). Also, using iExplorer I noticed Photo.apps has only a copy of each photo (it doesn't even have a small thumbnail copy for the gallery).
What technique did Apple use to make Photos.app so fast? How can I get that same performance in my app?
I'm a bit confused if this should be here or on Programmers,
since there's no code in the question, but F.A.Q. says that algorithm
questions are part of Stackoverflow, and the tags here match it
better.
So if you just show one image fullscreen you can do this:
In the WWDC11 Session 104 - Advanced Scroll View Techniques they talk about infinite scrolling and how to do it. The basic idea is to scroll the view and after scrolling reposition the (UIImage)view inside the scroll view so it appears centered or whatever you layout constraints are.You could then load the new UIImage into the UIImageView. Since you only have one UIImageView it should be pretty low memory consuming. I am not sure about how the loading times of the images will behave though.
Maybe preload the next UIImage to the left and right to the current image and then load it into the UIImageView after reposition the scrollView can help here.
For anyone who is still looking for simply implementation of scroll view that hold lot's of images.
https://github.com/sumofighter666/ReusableScrollView
It is as simply as implementing UITableView
I've built a scroller prototype using WebGL. The problem is, when it's combined with other non-WebGL elements on the same page, the scroller becomes jittery and the quality is quite poor. You can see a demo here (scroller is at the bottom, ignore the Chinese characters) - http://viewer-test.appspot.com/Viewer.html?type=presentation&id=6a169bb8-e440-4338-9e3a-8b5e429f32ee&showui=false Even if I take out the video, the scroller still slows when the CPU spikes every time that RSS feed top right shows a new feed snippet.
I had considered using Web Workers to run the scroller on a different thread, but came across another post in this forum that said that Web Workers can't be used with WebGL. What are my other options to ensure smooth scrolling?
Thx.
Are you using RequestAnimationFrame for your animation callbacks? If not, you should. It's managed by the browser to time the draw of your element with the others on the page and with the system screen sync, so you get the smoothest presentation possible. If you do your animation using setTimeout or setInterval, you'll almost always end up out of sync with the pages rendering, which leads to dropped frames and stutters.
I have a script that takes lots of content and builds 1000s of MovieClips on the stage, does lots of drawing etc. Due to the high amount of work needed when the frame first loads this can sometimes be delayed by a second or two.
The more the user uses the application the longer and longer this is likely to be (more data to siphon through and build).
My question to you is how do I make sure the frame doesn't show (serve a loading image or something) until it is built? I don't want the user to see the skeleton of the page and then everything appear a second or two later.
The way we do it:
Frame 1 is a loading frame. It simply continually polls progress (onEnterFrame) until it is sufficiently "complete" to move on to the frame that is needed. In your case, it might be that you're testing to see if you've instantiated enough objects, in our case it was whether framesloaded was sufficiently high.
We often put a "loading graphic" in frame 1. Other than that we have the "am I ready to finally move on yet?". Most recently our loader just had a circle which continued rotating.
As a side note: wait until everything is completely ready if you're working with an AS3 loader. Loading half-cocked left me working until 3 AM on Easter one year. I was not happy.