I'm working on an iPhone game that uses an MKMapView as the playfield. After only a couple of minutes of play the app inevitably starts to get sluggish and eventually crashes due to low memory. After digging around the culprit seems to be that the map view constantly demands more memory. The game requires a lot of zooming and panning of the map so I can only assume that the map's cache of tiles just keeps growing until it runs out of memory. Is there any way to force the map view to flush it's cache of tiles or contain it's memory consumption?
* NOTE: This answer is only relevant to iOS 4.1 and lower. The problems described in this answer were mostly fixed in iOS 4.2 *
I've been doing some digging on this as my app uses both the map and also has other features that demand high RAM.
I haven't found an answer, but a workaround. MKMapView's memory demands escalate exponentially as you zoom closer in to an area, and pan around within that zoomed in area.
There are two levels of MKMapView tile cache. One manifests itself as a Malloc ~196kb in Instruments, the other is NSData (store) of varying sizes.
The Malloc appears to be the active in-use tiles, and there is a hard cap on how many can be allocated. In my app that number is 16, not sure if its based on UIView size or not. These allocations seem to be stringently managed, and it responds to memory warnings.
Anyway, at a certain zoom level, say, continent level (enough to fit most of North America in an iPad screen), given the size of the tiles, if never really has to get to that second level of caching (NSData (Store)) in order to complete the map. Everything is crisp and clean. If I load in a ton of external images into active memory, the tiles prune themselves. Awesome!
The problem comes when it hits that second level of caching. This happens when you zoom in, and suddenly instead of 16 tiles to show the entire planat, it needs 16 tiles just to show off Los Angelas, and as you pan around instead of just dumping those old tiles it puts them into the NSData (store) allocations where they seem to never get freed.
This NSData (store) is the NSURLConnectionCache which exists by default only in memory. You can't access this cache to limit it, because it's not the default shared cache (already tried it).
So this is where I get stuck.
The unsatisfying answer is that if you disable map zooming and fix it at a reasonably broad zoom level, you can avoid this problem completely, but obviously some apps need this... and that's as far as I got.
I filed a support ticket with Apple to see if they can divulge any way to limit this ridiculous cache for the map (which by the way I was able to casually crank up to 50+ megs of RAM allocated in active memory).
Hope this helps.
edit
The next iOS release appears to have solved this limitless cache issue. MKMapView now aggressively prunes its cached tile data. REJOICE!
Are you setting the reuse identifier on your annotation views? (This means the system can detach those views and only keep a small number of views in memory at once. It also increases scrolling performance, because scrolling will reuse the detached views.)
Use this method to get an annotation view to be reused:
- (MKAnnotationView *)dequeueReusableAnnotationViewWithIdentifier:(NSString *)identifier
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With