How can I make a UIScrollView with a large image that displays fast (like Photos.app)?
I'm trying to make a simple image viewer for viewing the full resolution image of an ALAssetRepresentation. It turns out it's not quite that simple.
My first approach was to just make a big UIImageView inside the UIScrollView. While this did work, it was very slow.
When using the Photos app, when you touch an image, the larger version opens instantly. At first, there's a very low resolution image being drawn. But shortly, a higher resolution image appears. Also, if I zoom in, the image is first lower resolution and then the resolution increases.
I checked out the WWDC 2010 keynote #104 where it is described how Photos.app works. But how am I supposed to implement this? In the keynote, the demo uses pre-tiled images, something which I cannot get from an ALAssetRepresentation just like that. I've tried just loading the full resolution version and just drawing it using CATiledLayer and while it's not slow for zooming et.c, it's way too slow when drawing the tiles.
Is Photos.app caching a lower r开发者_高级运维esolution version of all images somewhere or what's going on? Some pointers on what to do would be helpful.
Yes, Photos.app is caching lower resolutions images. The good news is that you can get at those cached versions too. You're probably already aware of the fullScreenImage property of ALAssetRepresentation and the thumbnail property of ALAsset. Those should be much quicker to load.
What I've found with high resolution images is that just loading it can take 1-2 seconds, so I'm guessing that just doing the loading of the high res image in the background might do the trick for you.
So, how to load the low-res version of the image and then switch to the high-res version when you have i?. It can be a bit complicated, but hopefully this should get you started. Since you're using AssetsLibrary, you're going to have to use iOS 4, which is good news because you can do this fairly easily with blocks and GCD/libdispatch. I'm glad you're watching the WWDC videos--check out sessions 206 and 211 for lots of great info on GCD.
The basic idea is this that you're going to display the lower resolution version on the main thread, then ask a background thread to load the full resolution image, then tell the CATiledLayer to switch to the full resolution image.
- (void)displayAsset:(ALAssetRepresentation *)asset {
UIImage *lowresImage = [UIImage imageWithCGImage:asset.fullScreenImage
orientation:asset.orientation scale:asset.scale];
// Add code here to display the lowresImage
dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
^ {
// Load the full resolution image from the asset
UIImage *highresImage = [UIImage imageWithCGImage:asset.fullResolutionImage
orientation:asset.orientation
scale:asset.scale];
// Once done, tell the main thread to display the tiles
dispatch_async( dispatch_get_main_queue(),
^ {
// Code to swap out the lowresImage for highresImage
});
});
}
精彩评论