2

当我使用 UIHostingController 将新的 SwiftUI.View 推送到现有 UIKit UIViewController 的导航堆栈时,导航栏中的标题动画被破坏。我在 Xcode 12.0 中对一个纯新项目进行了测试。

仔细观察标题“UIHostingController”。您可以看到动画看起来与普通推送动画有何不同,它只是“出现”无中生有,看起来很破碎。第二个动画已经从 SwiftUI.NavigationLink 发生,看起来不错。

如果您想尝试一下,这里是示例项目的链接: https ://www.dropbox.com/s/mjkuzhpsb6yvlir/HostingControllerTest.zip?dl=0

查看此 GIF 图片:(如果您没有查看 GIF 动画,请在另一个浏览器选项卡中打开)

在此处输入图像描述

这是后面的代码:

class ViewController: UIViewController {
    private let button = UIButton(frame: .zero)

    override func viewDidLoad() {
        super.viewDidLoad()
        self.title = "UIHostingController Title Test"
        self.view.backgroundColor = UIColor.white
        
        self.view.addSubview(self.button)
        button.translatesAutoresizingMaskIntoConstraints = false
        button.setTitle("Push UIHostingController", for: .normal)
        button.addTarget(self, action: #selector(Self.pushVC), for: .touchUpInside)
        button.setTitleColor(.blue, for: .normal)
        
        NSLayoutConstraint.activate([
            button.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
            button.centerYAnchor.constraint(equalTo: self.view.centerYAnchor),
            button.widthAnchor.constraint(equalTo: self.view.widthAnchor),
            button.heightAnchor.constraint(equalToConstant: 50)
        ])
    }
    
    @objc private func pushVC() {
        let vc = UIHostingController(rootView: Content())
        self.navigationController?.pushViewController(vc, animated: true)
    }
}

struct Content: View {
    var body: some View {
        NavigationLink(destination: Content2()) {
            Text("Push NavigationLink")
        }
        .navigationTitle("UIHostingController")
    }
}

struct Content2: View {
    var body: some View {
        Text("Coming from NavigationLink")
            .navigationTitle("Native SwiftUI View")
    }
}
4

2 回答 2

1

找到了这个问题的解决方案。UIHostingController实际上只是一个普通的UIViewController(带有一些 SwiftUI 的附加组件)。这意味着可用于 a 的所有内容UIViewController也可用于UIHostingController. 因此,解决方案是将与导航栏相关的所有内容设置为打开UIHostingController,而不是在包装的 SwiftUI 视图中。

let vc = UIHostingController(rootView: Content())
vc.title = "My custom title"

如果直接设置为 ,所有导航按钮也会更好地工作UIHostingController。一个很好的选择也是直接从UIHostingController那里派生并实现自定义所需的行为。

于 2022-01-09T12:21:42.827 回答
0

要强制UIHostingController设置其导航项,我们可以在单独的窗口中预渲染它:

let window = UIWindow(frame: .zero)
window.rootViewController = UINavigationController(rootViewController: hostingController)
window.isHidden = false
window.layoutIfNeeded()

该窗口甚至可以被缓存以预渲染其他视图。

于 2022-02-07T13:54:48.457 回答