监视MKMapView重绘事件

我有一些UI需要根据用户平移或缩放地图时对MKMapView的更改进行重绘。

目前我正在使用移动事件手势识别器和MKMapViewDelegate regionDidChangeAnimated消息来重绘我的依赖UI。 这是我需要的90%。

我遗漏的事件是从用户抬起手指(不再移动事件)到触发MKMapViewDelegate regionDidChangeAnimated消息的时间点。 在此期间,地图缓慢停止,我的依赖UI与不同步的地图图块内容相混淆。

是否有一个较低级别的API会在UIView(在本例中为MKMapView)内容重新绘制时通知我?

更新

我尝试创建一个代理MKMapView子类,它将drawRect调用转发到我提供的委托。 我得到了第一次抽奖活动,但后来都没有,所以这对我的困境没有帮助。

不幸的是,IIRC,MKMapView 不符合 @"region" KVO标准 。

您可能会破解在regionWillChangeAnimated设置NSTimerregionWillChangeAnimated ,使用它在scroll / pan / etc期间刷新UI,并在regionDidChangeAnimated丢弃它。 虽然不太优雅,但如果您需要非常快,它可能不适合您的需求。

或者,您可以在MKMapView的子视图中查找UIScrollView ,并观察其transform

(我还没有测试过这些。)

在任何情况下,我都怀疑监视MKMapView上的重绘事件是否有用: MKMapView使用CATiledLayer异步执行绘图,因此您甚至无法确定它何时完成。


编辑:这显然不适用于iOS 6.当然,这不应该是一个惊喜。 但是,据我所知,委托方法的行为相同,因此OP的问题仍然存在。 我没有寻找更新的解决方案。

讨厌发布这些解决方案,但是。 MKMapView本身有很多子视图。 在它的子视图层次结构中,有一个带有类MKTiledView的视图,它将TiledLayer作为图层。

实际上,您无法以“正常”方式解析渲染通知。

Tiled层通过不断调用-drawLayer来呈现它的内容:inContext:它的委托方法,MKTiledView是。 这些调用可以在不同的线程中同时执行。

您没有收到MKMapView的规范(更新),因为它没有自行更新。 只有它的基础内容正在更新。

所以。 总有更好的解决方案存在。 我的解决方案取决于视图层次结构和方法的混合。 这取决于你,使用与否。

创建类别方法,我们将“更新通知”发布到需要更新的自定义视图

 @implementation UIView (Custom) - (void)drawCustomLayer:(CALayer *)layer inContext:(CGContextRef)ctx { NSLog(@"Need to draw custom layer :%@ in context %@, Thread: %@", layer, ctx, [NSThread currentThread]); // Calling old method [self drawCustomLayer:layer inContext:ctx]; } @end 

//将MKTiledView的方法实现交换到我们的自定义实现

 #import  Class tileViewclass = NSClassFromString(@"MKMapTileView"); Class viewClass = NSClassFromString(@"UIView"); SEL originalSelector = @selector(drawLayer:inContext:); SEL newSelector = @selector(drawCustomLayer:inContext:); Method origMethod = class_getInstanceMethod(tileViewclass, originalSelector); Method newMethod = class_getInstanceMethod(viewClass, newSelector); method_exchangeImplementations(origMethod, newMethod); 

仍在寻找更好的解决方案。

MKMapView有许多重绘的子视图。 很难找到哪个视图或图层绘制…

或者,您可以尝试查找某些MKMapView属性已更改。 您可以使用Key Value Observing(KVO)机制来完成此操作。 http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/KeyValueObserving/KeyValueObserving.html

例如。 (属性可以更改为您需要的任何内容)

  [myMapView addObserver:self forKeyPath:@"region" options:NSKeyValueObservingOptionNew context:nil]; [myMapView addObserver:self forKeyPath:@"centerCoordinate" options:NSKeyValueObservingOptionNew context:nil]; 

你应该实现observeValueForKeyPath:ofObject:change:context:

 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { // Do something that you want with keyPath; } 

每当mapView为您定义的每个属性都有新值时,将触发此方法。