监视MKMapView重绘事件

时间:2012-01-23 05:33:20

标签: ios uiview mapkit

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

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

我失踪的事件是从用户抬起手指(不再移动事件)到触发MKMapViewDelegate regionDidChangeAnimated消息的时间点。在此期间,地图缓慢停止,我的依赖用户界面停留在不同步的地图图块内容中。

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

更新

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

3 个答案:

答案 0 :(得分:2)

IIRC,遗憾的是@"region" NSTimerregionWillChangeAnimated

您可能会在regionDidChangeAnimated中设置UIScrollView,在滚动/平移/等等过程中使用它来刷新UI,并在transform中丢弃它。虽然不太优雅,如果你需要非常快,它可能不适合你的需要。

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

(我没有测试过这些。)

无论如何,我怀疑监视CATiledLayer上的重绘事件是否有用:{{1}}使用{{1}}异步执行绘图,所以你甚至不能确定何时完成。


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

答案 1 :(得分:1)

讨厌发布这些解决方案,但是。 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 <objc/runtime.h>

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);

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

答案 2 :(得分:-1)

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

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

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

  [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为您定义的每个属性都有新值时,将触发此方法。