2025.01.31 工作變動(dòng)原因捶障,故將一些工作期間Tapd內(nèi)部寫(xiě)的Wiki文檔轉(zhuǎn)移到個(gè)人博客。
URLNavigator三方庫(kù)
跳轉(zhuǎn)失敗肤舞,經(jīng)過(guò)排查后發(fā)現(xiàn)獲取的UIViewcontroller.navigationController
為空的問(wèn)題解決紫新。父子控制器的
addChild
正確添加與移除步驟。
一李剖、問(wèn)題排查過(guò)程
問(wèn)題出現(xiàn)點(diǎn)源碼
tapd_44062861_1714122687_959.png
open func push(_ viewController: UIViewController, from: UINavigationControllerType? = nil, animated: Bool = true) -> UIViewController? {
guard (viewController is UINavigationController) == false else { return nil }
// 使用斷點(diǎn)排查芒率,發(fā)現(xiàn)在這里直接 { return nil }了,原因是獲取UIViewController.topMost?.navigationController的時(shí)候篙顺,navigationController為空偶芍,所以決定對(duì)topMost方法進(jìn)行排查。
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
}
一路斷點(diǎn)排查德玫,發(fā)現(xiàn)在 navigationController
這里直接 { return nil }了匪蟀,原因是獲取 UIViewController.topMost?.navigationController
的時(shí)候,navigationController為空宰僧,所以決定對(duì)topMost方法進(jìn)行排查材彪。
topMost方法
tapd_44062861_1714123000_598.png
// child view controller
for subview in viewController?.view?.subviews ?? [] {
if let childViewController = subview.next as? UIViewController {
// 最終調(diào)試發(fā)現(xiàn),三方庫(kù)獲取的childViewController并不是我正在顯示的控制器琴儿,而是拿的subView第一個(gè)子控制器(第一個(gè)添加的子控制器視圖)段化,導(dǎo)致為空,所以要對(duì)子控制器進(jìn)行添加造成、移除管理解決显熏。
return self.topMost(of: childViewController)
}
}
最終調(diào)試發(fā)現(xiàn),三方庫(kù)獲取的 childViewController
并不是我正在顯示的控制器晒屎,而是 拿的subView第一個(gè)子控制器(第一個(gè)添加的子控制器視圖)喘蟆,導(dǎo)致為空。
因?yàn)槲?只對(duì)子控制器做了添加(addChild)鼓鲁,然后使用 subView.ishidden
來(lái)控制隱藏出現(xiàn)的問(wèn)題履肃,所以要對(duì)子控制器進(jìn)行添加、移除管理解決坐桩。
二尺棋、父子控制器的addChild添加、移除正確管理
主控制器mainVC
// 在主控制器點(diǎn)擊 tab_A 切換子控制器
if title == "tab_A" {
// 添加子控制器1
let squareVC = UIViewController()
// 將VC添加到控制器上绵跷,建立父子關(guān)系膘螟,這時(shí)可以通過(guò)`parentViewController`訪(fǎng)問(wèn)到父控制器;調(diào)用`addChildViewController`系統(tǒng)會(huì)自動(dòng)調(diào)用`willMoveToParentViewController:`
addChild(squareVC)
// 將VC控制器的view添加到父控制器上
view.addSubview(squareVC.view)
// 調(diào)用VC的`didMoveToParentViewController`通知VC完成了父子關(guān)系建立碾局。
squareVC.didMove(toParent: self)
// 移除子控制器2
let myVC = UIViewController()
// 通知子控制器即將解除父子關(guān)系
myVC.willMove(toParent: nil)
// 將VC的view從父控制器移除
myVC.view.removeFromSuperview()
// 通過(guò)`removeFromParentViewController`真正解除父子關(guān)系荆残,并且系統(tǒng)會(huì)調(diào)用`didMoveToParentViewController:`
myVC.removeFromParent()
}
// 在主控制器點(diǎn)擊 tab_B 切換子控制器
else if title == "tab_B" {
// 添加子控制器2...
// 移除子控制器1...
// 原理同上
}
1. 子控制器添加:
- 將VC添加到控制器上,建立父子關(guān)系净当,這時(shí)可以通過(guò)
parentViewController
訪(fǎng)問(wèn)到父控制器内斯;調(diào)用addChildViewController
系統(tǒng)會(huì)自動(dòng)調(diào)用willMoveToParentViewController:
蕴潦。 - 將VC控制器的view添加到父控制器上。
- 調(diào)用VC的
didMoveToParentViewController
通知VC完成了父子關(guān)系建立俘闯。
2. 子控制器移除:
- 通知子控制器即將解除父子關(guān)系潭苞。
- 將VC的view從父控制器移除。
- 通過(guò)
removeFromParentViewController
真正解除父子關(guān)系真朗,并且系統(tǒng)會(huì)調(diào)用didMoveToParentViewController:
此疹。
最終修改后具體實(shí)現(xiàn):
tapd_44062861_1714123000_599.png
最最最后,完結(jié)撒花
告辭.jpeg