I have some UI that I need to redraw based on changes to an MKMapView when the user pans or zooms the map.
Currently I am using a move event gesture recogniser and MKMapViewDelegate regionDidChangeAnimated messages to redraw my dependant UI. This is 90% of what I need.
The events I am missing are from the point the user lifts their finger (no more move events) to when the MKMapViewDelegate regionDidChangeAnimated message is fired. During that period the map slowly pans to a halt and my dependant UI is stuck with map tile content that is out of synch.
Is there a lower level API that will notify me when UIView (in this case MKMapView) content is redrawn?
Update
I tried creating a proxy MKMapView subclass that forwarded drawRect calls onto my supplied delegate. I get the first draw event but none of the subsequent ones, so this doesn't help with my predicament.
IIRC, MKMapView is unfortunately not KVO-compliant for
@"region"
.You might hack you way setting up an
NSTimer
inregionWillChangeAnimated
, using it to refresh you UI during the scroll/pan/etc, and discarding it inregionDidChangeAnimated
. Not quite elegant though, and it may not suit your needs if you need to be really fast.Alternatively, you may look for the
UIScrollView
in MKMapView's subviews, and observe itstransform
.(I haven't tested any of these.)
In any case, I doubt that monitoring redraw events on a
MKMapView
will be of any use :MKMapView
usesCATiledLayer
to perform its drawing asynchronously, so you can't even be sure when it's done.Edit : This apparently does not work with iOS 6. Of course, this should not really come as a surprise. However, as far as I know, the delegate methods behave the same, so the OP's problem is still real. I haven't looked for an updated solution.
MKMapView has many subviews that redraws. It is very hard to find which view or layer drawed...
Alternatively you could try to find some of MKMapView properties are changed. You can do this with Key Value Observing (KVO) mechanics. http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/KeyValueObserving/KeyValueObserving.html
Eg. (properties can be changed to whatever you need)
And you should implement
observeValueForKeyPath:ofObject:change:context:
Whenever your mapView has new values for each property you defined, this method will be fired.
Hate to post THESE kind of solutions, but. MKMapView has many subview in itself. In it's subviews hierarchy there's an view with class MKTiledView, which have TiledLayer as layer.
So, actually, you can't resolve notifications of rendering in "normal" way.
Tiled layer renders it's contents by constantly calling -drawLayer:inContext: method of it's delegate, which MKTiledView is. Those calls can be performed simultaneosly in different threads.
You're not receiving norifications(updates) from MKMapView because it isn't updating itself. Only underlying contents of it are updating.
So. There's always better solution exists. My solution depends on view hierarchy and method's swizzling. It's up to you, to use it or not.
Creating category-method in which we will post "update notifications" to custom view that need to be updated
// Exchanging method implementation of MKTiledView to our custom implementation
Still looking for better solution.