将ios13.1升级到13.2时出现问题 - 导航链接 - 尝试弹出到不存在的视图控制器



我使用UIKit和swiftUI构建了一个应用程序。

它在ios13.1中运行良好,但在ios13.2中我有错误:

我在UIViewController中显示SwiftUI视图(使用HostingController。此视图由NavigationLink中封装的元素组成。当点击这个元素时,下一个视图不会显示,尽管导航栏还可以,当点击返回时,应用程序崩溃:

<Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Tried to pop to a view controller that doesn't exist.'>

这是一个与ios 13.2有关的错误吗?知道怎么修吗?

这是我的代码:

UI控制器:

<类MyController:UIViewController{

var delegate: MenuItemsDelegate?
let vc = UIHostingController(rootView: MyView_UI())
override func viewDidLoad() {
super.viewDidLoad()
if #available(iOS 13.0, *) {
view.backgroundColor = BACKGROUND_COLOR_D
} else {
view.backgroundColor = PALE_GREY
}
setupViews()
setNavigationBar()
}
func setupViews() {
addChild(vc)
view.addSubview(vc.view)
vc.didMove(toParent: self)
setupConstraints()
}

func setupConstraints() {
vc.view.translatesAutoresizingMaskIntoConstraints = false
[
vc.view.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
vc.view.centerXAnchor.constraint(equalTo: view.centerXAnchor),
vc.view.widthAnchor.constraint(equalTo: view.widthAnchor),
vc.view.bottomAnchor.constraint(equalTo: view.bottomAnchor),
].forEach {$0.isActive = true }
}

func setNavigationBar() {
title = ""
navigationItem.leftBarButtonItem = UIBarButtonItem(image: #imageLiteral(resourceName: "slidingNotif").withRenderingMode(.alwaysOriginal),  style: .plain, target: self, action: #selector(handleMenuToggle))
setNavigationRightBarButtons()
}
@objc func handleMenuToggle() {
delegate?.handleMenuToggle(forMenuOption: nil)
}

}>

MyView_UI:<var body:some视图{

ScrollView{
VStack(spacing: 15) {
HStack(alignment: .center, spacing: 20) {
NavigationLink(destination: SecondView_UI(some param )){
ThirdView_UI(some param), height: 150)
}
NavigationLink(destination: SecondView_UI(some param)){
ThirdView_UI(some, height: 150)
}
}
.buttonStyle(PlainButtonStyle())
//autres HStack(...)
}
}

}

>

MyView_UI和SecondView_UI显示良好,但返回时应用程序崩溃

问题是UIKit和SwiftUI之间的桥接中的一个错误。它在某种程度上与此有关,但这里的原因是UIHostingController作为子级嵌入到另一个UIViewController中。不幸的是,如果您使用一些标准的容器视图控制器,如UIPageViewController,也会发生这种情况。

以下是坠机前的一些日志:

// we have ViewController0 in the navigation stack
// here we push ViewController1, that embeds UIHostingController, in our case - EmbeddedHostingController
pushViewController(_:animated:)
viewController: ViewController1
viewControllers: [ViewController0]
viewControllers: [ViewController0, ViewController1]
// here we tap a NavigationLink
// we can see that the pushed view controller is DestinationHostingController, coming from the framework
pushViewController(_:animated:)
viewController: DestinationHostingController<AnyView>
viewControllers: [ViewController0, ViewController1]
viewControllers: [ViewController0, ViewController1, DestinationHostingController<AnyView>]
// here we tap back in the navigation bar
// the DestinationHostingController is being popped, as expected
popViewController(animated:)
viewControllers:[ViewController0, ViewController1, DestinationHostingController<AnyView>]
super.result: DestinationHostingController<AnyView>
viewControllers: [ViewController0, ViewController1]
// this is the wrong part - the framework is triying to pop our embedded hosting controller, but because it is not part of the navigation stack - we get a crash
popToViewController(_:animated:)
viewController: EmbeddedHostingController
viewControllers: [ViewController0, ViewController1]

一个有效的解决方法是使用自定义UINavigationController子类,覆盖popToViewController,并在viewController为UIHostingController类型时返回nil

有时还会发生另一种奇怪的崩溃——导航控制器试图弹出。

以下是一个示例解决方案:

private protocol HostingController {}
extension UIHostingController: HostingController {}
class RootNavigationController: UINavigationController {
override func popToViewController(_ viewController: UIViewController, animated: Bool) -> [UIViewController]? {
if #unavailable(iOS 13.3) {
if #available(iOS 13.2, *) {
if viewController is HostingController, viewController.parent !== self {
return nil
}
if viewController === self {
return nil
}
}
}
return super.popToViewController(viewController, animated: animated)
}
}

最新更新