Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/96.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 监视MKMapView重绘事件_Ios_Uiview_Mapkit - Fatal编程技术网

Ios 监视MKMapView重绘事件

Ios 监视MKMapView重绘事件,ios,uiview,mapkit,Ios,Uiview,Mapkit,当用户平移或缩放地图时,我需要根据对MKMapView的更改重新绘制一些UI 目前,我正在使用移动事件手势识别器和MKMapViewDelegate regionidchange动画消息来重新绘制我的从属用户界面。这是我需要的90% 我缺少的事件是从用户抬起手指(不再有移动事件)到触发MKMapViewDelegate regionDidChangeAnimated消息的时间点。在这段时间里,地图缓慢地平移到停止状态,我的从属用户界面被不同步的地图平铺内容卡住 当UIView(在本例中为MKMa

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

目前,我正在使用移动事件手势识别器和MKMapViewDelegate regionidchange动画消息来重新绘制我的从属用户界面。这是我需要的90%

我缺少的事件是从用户抬起手指(不再有移动事件)到触发MKMapViewDelegate regionDidChangeAnimated消息的时间点。在这段时间里,地图缓慢地平移到停止状态,我的从属用户界面被不同步的地图平铺内容卡住

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

更新


我尝试创建一个proxy MKMapView子类,将drawRect调用转发到我提供的委托上。我得到了第一个绘制事件,但没有后续事件,因此这无助于解决我的困境。

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

或者,您可以尝试查找某些MKMapView属性已更改。您可以使用键值观察(KVO)机制来实现这一点

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

您应该实现对象的observeValueForKeyPath:change:context:

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

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

IIRC,不幸的是,MKMapView适用于
@“region”

你可以在
区域willChangeAnimated
中设置
NSTimer
,在滚动/pan/etc期间使用它刷新UI,然后在
区域idChangeAnimated
中丢弃它。虽然不是很优雅,但如果你需要非常快的速度,它可能不适合你的需要

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

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

无论如何,我怀疑在
MKMapView
上监视重绘事件是否有任何用处:
MKMapView
使用
CATiledLayer
异步执行其绘制,因此您甚至无法确定何时完成



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

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

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

平铺层通过不断调用其委托的-drawLayer:inContext:method来呈现其内容,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);
#导入
类tileViewclass=NSClassFromString(@“MKMapTileView”);
Class viewClass=NSClassFromString(@“UIView”);
SEL originalSelector=@选择器(绘图层:inContext:);
SEL newSelector=@选择器(drawCustomLayer:inContext:);
方法origMethod=class_getInstanceMethod(tileViewclass,originalSelector);
方法newMethod=class\u getInstanceMethod(viewClass,newSelector);
方法交换实施(原始方法,新方法);

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

谢谢你,伙计。您关于MKMapView不符合KVO的观点为我节省了一些时间。在发布之前我已经尝试过定时器选项,正如你所怀疑的,它没有达到标准。您得到了这个提示,因为解决方案涉及到挖掘UIScrollView的视图继承人,并在contentOffset属性上使用KVO。您介意我用工作代码编辑您的答案吗?在ios6中,mkmapview似乎没有uiscrollview子视图:(OP或@n-b,你介意发布对你有用的代码吗?了解你正在观察的属性,看看它是否适用于较新版本的MapKit,这将是非常有用的。+1感谢建议的解决方案。最后它来得有点晚,因为我刚刚尝试了@nico_nico的UIScrollView建议,它工作得非常好。+1你的建议是一个很好的解决方案正如@nico_nico所指出的,MKMapView对这些属性不兼容KVO。我还注意到addObserver调用中的参数不太正确(mYMapView和self应该交换)。再次感谢。:)感谢您的回复@尼科·尼科是对的。我没有注意到MKMapView的KVO兼容性。我已经提交了与此相关的Apple Bug#13774496(不知道地图何时完成绘制),并创建了一个示例应用程序,以显示iOS6上仍然存在此问题:@iwasrobed Awesome!谢谢:)
#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);