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
Related
I am currently developing a weather app.
For now I have just implemented static background image on the Home page that vary depending on the current weather.
I would like to improve this feature in order to provide a better user experience.
I think that with the rapid growth of technology, hardware, wifi but even frameworks and developing tools we are able to make greater and greater Apps each days.
That's why I am really interested about knowing different ways to improve my App.
Moreover, I think that the proper/coolest way to differentiate my App from the weather-app market is to have unique features or at least "more enjoyable" than others.
I really don't know where to start, I have read 3 different posts on StackOverflow about animated background without success.
I would like to know which solution is better in order to implement animated background image.
Should I play a short video infinitely, like a GIF ?
In term of battery consumption, should I worry about that ? Even knowing that the average app-navigation time for a weather app is approximatively 47s.
PS: I am developing with Objective C.
If you have any suggestions, any informations, I'll take it.
Thank you in advance.
There is a way to create a continuously animated image. What you do is create a UIImage with a special initializer (see final line). You give this initializer the base name of an image, like “storm”. The understanding is that you will have several files named storm1.png, storm2.png, etc., the succession of which will constitute an animation. All you do is call the initializer and specify how long you’d like each animation frame to last, and all the rest is automatic. The image view that gets created will continue cycling through however many animation frames you have. As long as that image view is visible, Apple’s code will guarantee the image will be continuously animating. As soon as it gets to the end of the list (say, storm8 if you have 8 frames in your animation), it automatically starts over. At least in Swift, you don’t even have to tell it the file extension of the images.
If you want the image to cover the entire background of your view controller, just set up the imageView in Interface Builder to be pinned to the left, right, top, and bottom of the main view of your view controller.
Here’s the syntax for creating the continuously animated image in your code:
UIImage *image = [UIImage animatedImageNamed:#"storm.jpg" duration:0.5f];
Or in Swift:
let imageView.image = UIImage.animatedImageNamed("storm", duration: 0.5)
My application suppose to show images in full screen and i have lots of images in my list(more than 500 images).
I'm adding image view in scroll view with horizontal scrolling and paging. But I'm facing memory issues as loaded images will eat my device memory?
What is the best way to load images.
Don't attempt to use a vanilla UIScrollView to show a ton of content, especially if you're just going to dump it all in at load-time. As you've seen, that will inevitably crash due to memory pressure.
At a minimum use UICollectionView, which will at least reuse cells and allow a minimum of assets to be in memory at one time. However, the problem of a smooth, low-memory photo collection view is one that many apps encounter, and can have a lot of implementation gotchas. I recommend looking for a well-built component rather than trying to reinvent that particular wheel.
I'm looking for a way to draw "Lines" above a UIWebView.
I have a UIWebView that display a PDF file, the user should be able to add "Lines" and "Sketches" (simple one color lines etc) for sure this could be done with a UIView on top of the UIWebView but i m running into 2 logical problems.
First can the UIView where the drawing is, be transparent beside the lines - so you can view the pdf through it?
How could i handle the zooming in the PDF, if a user zoom the WebView, the UIView have to zoom "with each other" - so the drawing stays at the same spot/zoom level?
Is there any other way to display a PDF and add drawings/annotations to it? Currently i m using a QLPreviewController where i see no way to add any kind of annotations?
Is three any best practice for this?
PSPDFKit handles this (and many other hard PDF problems) very well. Using a web view for this kind of problem is likely to have many little corner cases. Any commercial product that has non-trivial needs around PDFs should definitely start there. For open source projects I don't have a great answer beyond "yeah, PDFs are a pretty tough; good luck."
That said, here are some starting points that may help you.
You can turn off zooming with webView.scalesPageToFit = false
You can get the current zoom scale using webView.scrollView.zoomScale
I believe you can KVO observe zoomScale to track it while it changes, but you may only get the target value (which will cause you to lag).
You can disable zooming (scalesPageToFit) and then re-implement it yourself with a UIPinchGestureRecognizer and scrollView.setZoomScale(_:animated:). That way you could track the zoom changes better. You could also try to handle the animation yourself with a CABasicAnimation so that you could keep it in sync.
My experience with scroll views, web views, and PDF is that there are a lot of little funny interactions that will surprise you. Getting something that "kind of" works isn't that hard, but getting it really clean, smooth, and beautiful can be a nightmare. That's why I typically recommend PSPDFKit to clients. You'll generally spend much less on the license than on the custom development.
I am building my first project that is an interactive ebook app for the iPad
I started with the Single View App template from XCode
So far, the project is mostly a series of block animated transitions between UIImageViews and MPMovieController videos, very serial so far
Everything is coded within a single view under a single view - the image views fade in and out with alpha animations
I am beginning to run into memory issues. I've used memory instruments and see that most everything is loaded into memory at the beginning (images from the InterfaceBuilder) aside from some videos instantiated at runtime
My question is - how should I reorganize my code to better utilize memory? Should I separate into different views under one view controller, or have multiple view controllers?
And which might be the most straight forward to implement?
Images are very memory-intensive. So:
Do not load an image until you actually need it (for display). When you are done with it (the image view is no longer visible), release it (by setting that image view's image to nil). Do not maintain the images in an array or anything like that. Do not create the image views preloaded with images in advance in the nib.
When you actually need an image for display, load it in code using imageWithContentsOfFile:, not imageNamed:. Thus you prevent caching of the image.
It is a waste of memory to work with an image larger than the display size. If these images are large, you can save a lot of memory up front if you load the image at the actual size needed for display. This is easy to do with Image IO framework and CGImageSourceCreateThumbnailAtIndex.
I think you need to use multiple view controllers and separate your code in small separated views and objescts that controll you app flow..
On the one hand it's better to have multiple views and so on..but it's a pain to rewrite code you worked on (unless it's absolutely necessary).
In my opinion if you don't have anything unnecessary in memory (i.e. when you take a view off screen you release the memory it used) you don't need to do anything.
After all, even if you split the code as it should have been, if your memory management is good, it will take the exact same memory.
You should be able to do this with a single view controller:
Load your images lazily from code. Keep an array of the image names rather than the images themselves, and load them just before you need them.
Make sure your images aren't larger than they need to be.
Recycle your image views. If the user won't see more than two image views at a time (including both the from and to in a transition), you should only have two image views.
Don't worry about whether the images are cached; iOS's caches are designed to release their contents under stress. That said, do not implement your own caching system. You might not release images properly under stress. If you need caching, use NSCache.
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