导航控制器数组中视图控制器索引始终为nil问题求助
问题分析与解决方案
你遇到的index(of:)始终返回nil的问题,核心原因是对象引用不相等——index(of:)方法是通过引用相等性(===)来匹配对象的,只有当你传入的controller实例和导航栈里的某个VC是完全同一个对象(内存地址一致)时,才能找到对应的索引。哪怕两个VC是同一个类的实例,只要不是同一个对象,index(of:)就会返回nil,这也就能解释为什么你能看到数组里有目标VC,但就是找不到索引的情况。
下面给你几个可行的解决办法:
1. 先确认引用是否一致
先验证你传入的controller和导航栈里的VC是不是同一个实例,你可以打印它们的内存地址来对比:
// 打印传入的controller的内存地址 print("传入的控制器地址:", Unmanaged.passUnretained(controller).toOpaque()) // 遍历导航栈里的VC,打印每个的地址 for vc in arrayOfVCs { print("栈内控制器地址:", Unmanaged.passUnretained(vc).toOpaque()) }
如果地址不一样,说明你传入的是另一个实例,这时候index(of:)自然找不到。
2. 改用基于特征的查找(替代引用匹配)
如果没法保证引用一致,可以通过VC的类、自定义标识等特征来查找索引:
方式一:通过类名查找
如果导航栈里只有一个该类的VC,直接用firstIndex(where:)匹配类型:
if let index = arrayOfVCs.firstIndex(where: { $0 is YourTargetVCClass }) { // 找到目标索引,执行移除操作 (currentWindow.rootViewController as! UINavigationController).viewControllers.remove(at: index) }
方式二:通过自定义标识查找
先给目标VC设置一个唯一的restorationIdentifier:
// 在目标VC的初始化代码里设置 self.restorationIdentifier = "UniqueTargetVCID"
然后在查找时匹配这个标识:
if let index = arrayOfVCs.firstIndex(where: { $0.restorationIdentifier == "UniqueTargetVCID" }) { (currentWindow.rootViewController as! UINavigationController).viewControllers.remove(at: index) }
3. 优化导航控制器的获取方式(iOS 13+适配)
另外,你当前用UIApplication.shared.keyWindow获取窗口的方式在iOS 13以后的多场景App里可能不太可靠,建议改用场景来获取当前活跃窗口:
public func removeFromStack(controller : UIViewController) { guard let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene, let currentWindow = scene.windows.first(where: { $0.isKeyWindow }), let navController = currentWindow.rootViewController as? UINavigationController else { return } let arrayOfVCs = navController.viewControllers if let index = arrayOfVCs.firstIndex(where: { $0 === controller }) { navController.viewControllers.remove(at: index) } }
内容的提问来源于stack exchange,提问作者Shamil
相关产品推荐
相关产品推荐

