As you have already found out it is not very fast to draw UIImage objects yourself. I had myself a similar requirement in a previous project, and did various tests to try to find an efficient enough method to get fairly small bitmaps on screen. While in no way claiming to know the full truth on the subject, I think I have same interesting pieces of information to share.
CALayer + contents
What I found was (as Palle says in his brief comment) that CALayer with the bitmap set to its contents property was the fastest way to do it. Probably not nearly as fast as metal or OpenGL, but magnitudes faster than draw. It seems that when you add a layer to the screen it ends up in the GPU memory, so repositioning such layers on (or off) screen is very fast. You can also do transforms (in 3D) on these layers with little penalty. Also, as I understand it, using the same bitmap as contents for many layers will actually share memory on the GPU as well.
If you haven't worked with layers before it's fairly straight forward. On iOS every UIView is backed by a CALayer, in practice it means that you can easily get to a layer by just doing view.layer.
Creating a bitmap backed layer is easy, just instantiate it and set the contents, then add it to your view controller's layer (or wherever you want it).
CALayer *layer = [CALayer layer]; layer.contents = [UIImage imageNamed:@"yourImage"].CGImage; [self.view.layer addSublayer:layer];
A final note on working with layers. By default all CALayer objects have animations attached to them for various property changes. This is handy if you, for example, want to animate a move of an object, because all you have to do is to set the new position. However, this might not be what you want if you are doing your own scenery, and perhaps animating with CADisplayLink. In such case you must remove these default animations, or they will interfere with your updates.
Remove implicit animations from a CALayer objects
- (void)removeAnimationFromLayer:(CALayer *)layer { layer.actions = @{ @"contents": [NSNull null], @"position": [NSNull null], @"frame": [NSNull null], @"opacity": [NSNull null], @"bounds": [NSNull null], @"affineTransform": [NSNull null], @"sublayerTransform": [NSNull null], @"transform": [NSNull null], @"zPosition": [NSNull null], @"anchorPoint": [NSNull null], @"cornerRadius": [NSNull null], @"sublayers": [NSNull null], @"onLayout": [NSNull null], }; }
UIImageView
Almost as fast as layers are (perhaps surprisingly) UIImageView objects when used correctly. They too, seem to be highly optimized and very fast to move around on screen. My experience is that you should try not to re-assign the image on the UIImageView, but rather use separate UIImageView objects for different images. As with layers, you should try to only do positioning and transforms on the objects to maintain speed.
A notable difference between UIImageView and CALayer is that CALayer is for output only, while UIImageView, as being a descendant of UIView and UIResponder, also handles input. This can be worth the trade-off if you need it. Another difference is that UIImageView usually is a bit easier to work with.
I recommend you do a few test of your own to see what performance you get. UIImageView might get you all the way!
CALayer contents property
CALayerinstances to display the images using thelayer.contentsproperty. The layer is only rendered once and from there on things should be pretty fast.