2025.01.31 工作变动原因,故将一些工作期间Tapd内部写的Wiki文档转移到个人博客。
URLNavigator三方库
跳转失败,经过排查后发现获取的UIViewcontroller.navigationController
为空的问题解决。父子控制器的
addChild
正确添加与移除步骤。
一、问题排查过程
问题出现点源码
open func push(_ viewController: UIViewController, from: UINavigationControllerType? = nil, animated: Bool = true) -> UIViewController? {
guard (viewController is UINavigationController) == false else { return nil }
// 使用断点排查,发现在这里直接 { return nil }了,原因是获取UIViewController.topMost?.navigationController的时候,navigationController为空,所以决定对topMost方法进行排查。
guard let navigationController = from ?? UIViewController.topMost?.navigationController else { return nil }
guard self.delegate?.shouldPush(viewController: viewController, from: navigationController) != false else { return nil }
navigationController.pushViewController(viewController, animated: animated)
return viewController
}
一路断点排查,发现在 navigationController
这里直接 { return nil }了,原因是获取 UIViewController.topMost?.navigationController
的时候,navigationController为空,所以决定对topMost方法进行排查。
topMost方法
// child view controller
for subview in viewController?.view?.subviews ?? [] {
if let childViewController = subview.next as? UIViewController {
// 最终调试发现,三方库获取的childViewController并不是我正在显示的控制器,而是拿的subView第一个子控制器(第一个添加的子控制器视图),导致为空,所以要对子控制器进行添加、移除管理解决。
return self.topMost(of: childViewController)
}
}
最终调试发现,三方库获取的 childViewController
并不是我正在显示的控制器,而是 拿的subView第一个子控制器(第一个添加的子控制器视图),导致为空。
因为我 只对子控制器做了添加(addChild),然后使用 subView.ishidden
来控制隐藏出现的问题,所以要对子控制器进行添加、移除管理解决。
二、父子控制器的addChild添加、移除正确管理
主控制器mainVC
// 在主控制器点击 tab_A 切换子控制器
if title == "tab_A" {
// 添加子控制器1
let squareVC = UIViewController()
// 将VC添加到控制器上,建立父子关系,这时可以通过`parentViewController`访问到父控制器;调用`addChildViewController`系统会自动调用`willMoveToParentViewController:`
addChild(squareVC)
// 将VC控制器的view添加到父控制器上
view.addSubview(squareVC.view)
// 调用VC的`didMoveToParentViewController`通知VC完成了父子关系建立。
squareVC.didMove(toParent: self)
// 移除子控制器2
let myVC = UIViewController()
// 通知子控制器即将解除父子关系
myVC.willMove(toParent: nil)
// 将VC的view从父控制器移除
myVC.view.removeFromSuperview()
// 通过`removeFromParentViewController`真正解除父子关系,并且系统会调用`didMoveToParentViewController:`
myVC.removeFromParent()
}
// 在主控制器点击 tab_B 切换子控制器
else if title == "tab_B" {
// 添加子控制器2...
// 移除子控制器1...
// 原理同上
}
1. 子控制器添加:
- 将VC添加到控制器上,建立父子关系,这时可以通过
parentViewController
访问到父控制器;调用addChildViewController
系统会自动调用willMoveToParentViewController:
。 - 将VC控制器的view添加到父控制器上。
- 调用VC的
didMoveToParentViewController
通知VC完成了父子关系建立。
2. 子控制器移除:
- 通知子控制器即将解除父子关系。
- 将VC的view从父控制器移除。
- 通过
removeFromParentViewController
真正解除父子关系,并且系统会调用didMoveToParentViewController:
。
最终修改后具体实现: