我想移动 MKMapView 指南针。我想通过这样的方式获得参考:
let compassView = mapView.subviews.filter {$0 is NSClassFromString("MKCompassView")}
然而编译器抱怨“使用未声明的类型‘NSClassFromString’”。 我该如何修复此代码?
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)
}
对于 iOS 11 及更高版本,请使用
MKCompassButton
。
let compass = MKCompassButton(mapView: mapView)
这是我通过子类化 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)
}
}
}
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)})
}
}