作者:林斯诺_SNOW | 来源:互联网 | 2023-01-15 19:46
在iOS11
该zPosition
停止的annotationView.layer工作.每次地图区域发生变化.
原始解决方案没有运气:layer.zPosition = X;
没有运气bringViewToFront
/ SendViewToBack
方法
Xcode 8.3/9
更新(解决方案感谢Elias Aalto):
创建MKAnnotationView时:
annotationView.layer.zPosition = 50;
if (IS_OS_11_OR_LATER) {
annotationView.layer.name = @"50";
[annotationView.layer addObserver:MeLikeSingleton forKeyPath:@"zPosition" options:0 context:NULL];
}
在MeLikeSingleton或你在那里的任何观察者对象:
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context {
if (IS_OS_11_OR_LATER) {
if ([keyPath isEqualToString:@"zPosition"]) {
CALayer *layer = object;
int zPosition = FLT_MAX;
if (layer.name) {
zPosition = layer.name.intValue;
}
layer.zPosition = zPosition;
//DDLogInfo(@"Name:%@",layer.name);
}
}
}
此解决方案使用layer.name值来跟踪zOrder.如果您有多个级别的zPosition(用户位置,群集,引脚,标注);)
不用于循环,只有KVO
我使用了一个Singleton Object来观察图层值的变化.如果您在整个应用程序中使用了多个MKMapView.
它是如何在IOS11之前工作的
..是用的
- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views
并在此处设置zPosition.
..但是(对于我们中的一些人,仍然是dunny为什么)在iOS11中不再起作用了!
1> Elias Aalto..:
zPosition 确实有效,只是MKMapView基于有点破碎和无用的MKFeatureDisplayPriority在内部覆盖它.如果你只需要一些注释来坚持"其他一切",那么你可以使用KVO 半干净地完成这项工作.只需将一个观察者添加到注释视图的图层的zPosition中,并在MKMapView试图摆弄它时覆盖它.
(请原谅我的ObjC)
添加观察者:
[self.annotationView.layer addObserver:self forKeyPath:@"zPosition" options:0 context:nil];
否决MKMapView
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
{
if(object == self.annotationView.layer)
{
self.annotationView.layer.zPosition = FLT_MAX;
}
}
利润
2> bteapot..:
我们可以完全忽略MKMapView
修改MKAnnotationView
层的尝试zPosition
。由于MKAnnotationView
使用standard CALayer
作为其层而不是某些私有类,因此我们可以对其进行子类化并覆盖其zPosition
。要进行实际设置,zPosition
我们可以提供我们自己的访问器。
它的工作速度比KVO快得多。
class ResistantLayer: CALayer {
override var zPosition: CGFloat {
get { return super.zPosition }
set {}
}
var resistantZPosition: CGFloat {
get { return super.zPosition }
set { super.zPosition = newValue }
}
}
class ResistantAnnotationView: MKAnnotationView {
override class var layerClass: AnyClass {
return ResistantLayer.self
}
var resistantLayer: ResistantLayer {
return self.layer as! ResistantLayer
}
}
更新:
点击重叠的注释时,我有一个非常优雅的方法可以选择最上面的注释视图。
class MyMapView: MKMapView {
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
// annotation views whose bounds contains touch point, sorted by visibility order
let views =
self.annotations(in: self.visibleMapRect)
.flatMap { $0 as? MKAnnotation }
.flatMap { self.view(for: $0) }
.filter { $0.bounds.contains(self.convert(point, to: $0)) }
.sorted(by: {
view0, view1 in
let layer0 = view0.layer
let layer1 = view1.layer
let z0 = layer0.zPosition
let z1 = layer1.zPosition
if z0 == z1 {
if let subviews = view0.superview?.subviews,
let index0 = subviews.index(where: { $0 === view0 }),
let index1 = subviews.index(where: { $0 === view1 })
{
return index0 > index1
} else {
return false
}
} else {
return z0 > z1
}
})
// disable every annotation view except topmost one
for item in views.enumerated() {
if item.offset > 0 {
item.element.isEnabled = false
}
}
// re-enable annotation views after some time
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
for item in views.enumerated() {
if item.offset > 0 {
item.element.isEnabled = true
}
}
}
// ok, let the map view handle tap
return super.hitTest(point, with: event)
}
}