如何重新定位MKMapView的指南针?

问题描述 投票:0回答:4

我想移动 MKMapView 指南针。我想通过这样的方式获得参考:

let compassView = mapView.subviews.filter {$0 is NSClassFromString("MKCompassView")}

然而编译器抱怨“使用未声明的类型‘NSClassFromString’”。 我该如何修复此代码?

ios swift mapkit mkmapview ios11
4个回答
7
投票

iOS 11

你应该使用

MKCompassButton
,解释新内容的文档:WWDC 2017 新的 MapKit 演示

let compassButton = MKCompassButton(mapView:mapView)
compassButton.frame.origin = CGPoint(x: 20, y: 20)
compassButton.compassVisibility = .visible
view.addSubview(compassButton)

iOS < 11

您可以尝试使用

String(describing:)
,例如:

if let compassButton = (mapView.subviews.filter { String(describing:$0).contains("MKCompassView") }.first) {
   print(compassButton)
}

1
投票

对于 iOS 11 及更高版本,请使用

MKCompassButton

let compass = MKCompassButton(mapView: mapView)

1
投票

这是我通过子类化 MKMapView 来重新定位罗盘视图的解决方案。
代码是Swift 5.0,在iOS10及以上版本上测试。
注意:当您在 iOS10 设备上测试此功能时,您必须旋转地图以使指南针可见。

import MapKit
class MapView: MKMapView {
    override func layoutSubviews() {
        super.layoutSubviews()
        if #available(iOS 10.0, *) {
            self.showsCompass = true //*** - You have to set this true here, it does not work if you set it on storyboards or in a View Controller - ***
            if let compassButton = (self.subviews.filter { String(describing:$0).contains("MKCompassView") }.first) {
                compassButton.frame = CGRect(x: 20, y: 40, width: 36, height: 36)
            }
        } else {
            let compassButton = MKCompassButton(mapView:self)
            compassButton.frame.origin = CGPoint(x: 20, y: 40)
            compassButton.compassVisibility = .visible
            self.addSubview(compassButton)
        }
    }
}

0
投票

截至 iOS 15 / 2024 的当前答案

旧的“移动 MKCompassView”方法不起作用

Apple 改变了视图结构。如果您尝试移动 MKCompassView 的框架,您会发现它什么也没做。不要浪费你的时间。 (FWIW 理论上您正在使用隐藏类,因此该应用程序可能会被 Apple 拒绝。)

你只需这样做

///MapView with rose in different position
class BetterMKMapView: MKMapView {
    
    lazy var comp: MKCompassButton = {
        let v = MKCompassButton(mapView: self)
        v.isUserInteractionEnabled = true
        addSubview(v)
        return v
    }()
    
    override func layoutSubviews() {
        super.layoutSubviews()
        showsCompass = false
        comp.frame = CGRect(
            origin: CGPoint(x: 666, y: 666),
            size: comp.bounds.size)
    }
}

一切工作原理在各方面都与标准指南针完全相同。出现、消失、点击、动画等

请注意,“showsCompass”的命名(令人惊讶)很糟糕,它应该命名为 includeDefaultCompass 之类的名称。 “showsCompass”对您包含的任何指南针都没有影响。

仅供参考,如果您想匹配其中一些值,目前(2024 年)默认指南针是从右侧插入 64,从顶部插入 49。因此...

你只需这样做 - 如果你想要右下角,复制粘贴

/// Bottom-right rose; match (current) Apple feel
class DesignishMKMapView: MKMapView {
    
    lazy var comp: MKCompassButton = {
        let v = MKCompassButton(mapView: self)
        v.isUserInteractionEnabled = true
        addSubview(v)
        return v
    }()
    
    override func layoutSubviews() {
        super.layoutSubviews()
        // FYI, for 2024, apple design is insets 49 top 64 right
        showsCompass = false
        comp.frame = CGRect(
            origin: CGPoint(x: bounds.width - 64 - comp.bounds.size.width,
                            y: bounds.height - 49 - comp.bounds.size.height),
            size: comp.bounds.size)
    }
}

如果您确实想移动提供的指南针,也许可以通过实验来移动

在撰写本文时很容易,

///Hah-hah Apple
class WeirdMKMapView: MKMapView {
    override func layoutSubviews() {
        super.layoutSubviews()
        if let compass = first(ofType: "MKCompassView") {
            compass.superview!.frame = CGRect(
                origin: CGPoint(x: 200, y: 200),
                size: compass.superview!.bounds.size)
        }
    }
}

但这可以而且将会改变任何时候苹果碰巧在愚弄它。

只是 FTR 实验性的,如果你没有这里的效用函数,那就是

extension UIView {
    var subviewsRecursive: [UIView] {
        return subviews + subviews.flatMap { $0.subviewsRecursive }
    }
    ///Find by type by string.
    func first(ofType: String) -> UIView? {
        return subviewsRecursive.first(where:
                         {String(describing: $0).contains(ofType)})
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.