在 Swift 中将自定义视图锚定到 Mapbox NavigationViewController 中的现有视图

Anchoring custom views to existing view in Mapbox NavigationViewController in Swift

我在 Swift 中的 iOS 上使用 Mapbox 框架来创建自定义 NavigationViewController。我需要帮助以获取 NavigationView.

FloatingStackView 的参考

我添加了一个额外的按钮(见屏幕截图的左上角),我想将它锚定到右侧的 FloatingStackView,以便它随着顶部横幅的变化而上下移动(类似于 FloatingStackView行为)。问题是我似乎无法访问 FloatingStackView。从我在 Mapbox 源代码中看到的,FloatingStackViewNavigationView 的子视图,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 设计,它可能会被破坏。根据应用程序的用户群,我可能会冒险匹配类型,但可能不是其他方式!

请注意,为简洁起见,我强制展开了上面的视图 - 您也希望在生产代码中更加谨慎:-)