在 Swift 中将自定义视图锚定到 Mapbox NavigationViewController 中的现有视图
Anchoring custom views to existing view in Mapbox NavigationViewController in Swift
我在 Swift 中的 iOS 上使用 Mapbox 框架来创建自定义 NavigationViewController。我需要帮助以获取 NavigationView
.
上 FloatingStackView
的参考
我添加了一个额外的按钮(见屏幕截图的左上角),我想将它锚定到右侧的 FloatingStackView,以便它随着顶部横幅的变化而上下移动(类似于 FloatingStackView行为)。问题是我似乎无法访问 FloatingStackView。从我在 Mapbox 源代码中看到的,FloatingStackView
是 NavigationView
的子视图,RouteMapViewController
是 NavigationViewController 的 mapViewController
的视图。问题是我无法访问 mapViewController,因为它由于内部保护级别而无法访问。
这是我想做的一个例子:
import UIKit
import MapboxNavigation
class DemoNavigationViewController: NavigationViewController {
override func viewDidLoad() {
super.viewDidLoad()
let mapVC = mapViewController
// Do any additional setup after loading the view.
}
}
这是 let mapVC 行的错误:
'mapViewController' is inaccessible due to 'internal' protection level
我的最终目标是能够通过类似这样的方式访问 FloatingStackView:
let navigationView = mapViewController.view as? NavigationView
let floatingStackView = navigationView.floatingStackView
如果我可以获得对那个 floatingStackView 的引用,我想我可以处理布局。
如何解决 is inaccessible due to 'internal' protection level
错误或找到另一种访问浮动堆栈视图的方法?
来自 NavigationView class 源代码
如果标记为内部,您将无法直接引用它。然而,有一种 hacky 方法可以获取任何视图并将其用于 AutoLayout(假设该视图使用 autoLayout 并且具有您可以使用的锚点)。
由于每个视图都有一个 subViews
数组,您可以遍历子视图以找到您想要的那个。所有子视图都是可见的,即使是来自私有实例的子视图也是如此。诀窍是确定您需要的那个。
如果类型定义是可访问的,你可以这样做
let navView = viewController.subViews.first{[=10=] is NavigationView}!
let stackView = navView.subViews.first{[=10=] is UIStackView}!
floatingButton.topAnchor.constraint(equalTo: stackView.topAnchor).isActive true
如果您没有可以匹配的类型,您将不得不做一些更棘手的事情,例如匹配描述:.first{[=12=].description conatins "stack"}
。或者甚至通过索引 subView 数组进行反复试验,直到获得所需的结果,然后希望视图的顺序始终相同!
您是否愿意在生产代码中冒这个风险只是您可以做出的决定,因为如果库更改其 UI 设计,它可能会被破坏。根据应用程序的用户群,我可能会冒险匹配类型,但可能不是其他方式!
请注意,为简洁起见,我强制展开了上面的视图 - 您也希望在生产代码中更加谨慎:-)
我在 Swift 中的 iOS 上使用 Mapbox 框架来创建自定义 NavigationViewController。我需要帮助以获取 NavigationView
.
FloatingStackView
的参考
我添加了一个额外的按钮(见屏幕截图的左上角),我想将它锚定到右侧的 FloatingStackView,以便它随着顶部横幅的变化而上下移动(类似于 FloatingStackView行为)。问题是我似乎无法访问 FloatingStackView。从我在 Mapbox 源代码中看到的,FloatingStackView
是 NavigationView
的子视图,RouteMapViewController
是 NavigationViewController 的 mapViewController
的视图。问题是我无法访问 mapViewController,因为它由于内部保护级别而无法访问。
这是我想做的一个例子:
import UIKit
import MapboxNavigation
class DemoNavigationViewController: NavigationViewController {
override func viewDidLoad() {
super.viewDidLoad()
let mapVC = mapViewController
// Do any additional setup after loading the view.
}
}
这是 let mapVC 行的错误:
'mapViewController' is inaccessible due to 'internal' protection level
我的最终目标是能够通过类似这样的方式访问 FloatingStackView:
let navigationView = mapViewController.view as? NavigationView
let floatingStackView = navigationView.floatingStackView
如果我可以获得对那个 floatingStackView 的引用,我想我可以处理布局。
如何解决 is inaccessible due to 'internal' protection level
错误或找到另一种访问浮动堆栈视图的方法?
来自 NavigationView class 源代码
如果标记为内部,您将无法直接引用它。然而,有一种 hacky 方法可以获取任何视图并将其用于 AutoLayout(假设该视图使用 autoLayout 并且具有您可以使用的锚点)。
由于每个视图都有一个 subViews
数组,您可以遍历子视图以找到您想要的那个。所有子视图都是可见的,即使是来自私有实例的子视图也是如此。诀窍是确定您需要的那个。
如果类型定义是可访问的,你可以这样做
let navView = viewController.subViews.first{[=10=] is NavigationView}!
let stackView = navView.subViews.first{[=10=] is UIStackView}!
floatingButton.topAnchor.constraint(equalTo: stackView.topAnchor).isActive true
如果您没有可以匹配的类型,您将不得不做一些更棘手的事情,例如匹配描述:.first{[=12=].description conatins "stack"}
。或者甚至通过索引 subView 数组进行反复试验,直到获得所需的结果,然后希望视图的顺序始终相同!
您是否愿意在生产代码中冒这个风险只是您可以做出的决定,因为如果库更改其 UI 设计,它可能会被破坏。根据应用程序的用户群,我可能会冒险匹配类型,但可能不是其他方式!
请注意,为简洁起见,我强制展开了上面的视图 - 您也希望在生产代码中更加谨慎:-)