Not sure if this question is still relevant, but if so, maybe this will help:
I've fought the battle of efficient display of large views in my tiled image view as well. There are a bunch of underlying parts to the problem:
- A normal
UIView
, including UIImageView
, seems to always be completely backed by memory for its image. Even if you implement the drawRect:
method, it always seems to pass the entire bounds of the view, not only the area visible within a scroll view. As you've discovered, this quickly takes up a lot of memory as each pixel takes 4 bytes.
- The
CATiledLayer
does only request the contents for visible tiles. It also discards tiles that are no longer visible - this is where the memory savings come from. However, it does the notification and the drawing on a background thread, while animating from white to the contents. It seems to do this via a private API, I haven't found a way to re-implement CATiledLayer
's functionality as my own subclass of CALayer
, as there simply seems to be no notification mechanism that we can use as mere mortals.
- If you have multiple views within the scroll view, they receive
drawRect:
messages appropriately as they are paged in. UIKit seems to struggle with too many subviews below a view, though.
For you, I can see a couple of possible options:
- It might be possible to salvage the
CATiledLayer
-based implementation. The fadeDuration
defaults to 0.25 seconds, which may be too long if your load times are short. You can drop this right down to something like 1.0/60.0
, i.e. one frame. One thing that's not clear from your description is whether your images cover the whole page size or just each 256x256 pixel tile. Decoding the whole JPEG over and over again for each tile will be much slower than decoding individual tile files.
- If the latency from doing everything from the
CATiledLayer
thread is too high, you can manually create a bunch of tiles as UIImageView
subviews to a blank UIView
which is the main subview to the scroll view. Each of these subviews is assigned its own tile image. If you're lucky, UIKit will be smart enough to drop the contents of these views and re-load the corresponding JPEGs on demand.
- If UIImageViews aren't smart enough, or you have too many views for UIKit to cope, you can build your own views which load their JPEGs in
drawRect:
. If it's still too jerky, try with your own CALayers, which will be sublayers of your single view's blank layer and again load their image on demand. This is what I eventually went with for my tiled image view.
That should cover scrolling, but it could still be really slow if you allow the user to zoom right out (minification). In that case I recommend you store appropriate lower-resolution versions and load/show those at those outermost zoom levels.