iOS应用切换视图触发NSMutableRLEArray越界崩溃,求排查方案
解决NSRangeException崩溃:NSMutableRLEArray越界问题
嘿,我来帮你分析这个崩溃问题!这个NSMutableRLEArray objectAtIndex:effectiveRange:: Out of bounds错误,通常和Auto Layout约束异常或者视图控制器生命周期操作不规范有关,而且你说用segue切换也崩溃,说明问题大概率出在目标视图控制器(MyViewController)本身,或者切换过程中的视图层级处理上。下面是几个具体的排查和修复方向:
1. 先检查目标VC的Auto Layout约束
这是最常见的触发原因:
- 打开你的
MyViewController的storyboard/xib,看看有没有红色的约束警告,或者黄色的布局提示,这些都是约束不完整/冲突的信号。 - 你代码里手动设置了
vc.view.frame = rootViewController.view.frame然后调用layoutIfNeeded(),如果目标VC是用Auto Layout布局的,这行代码反而会和自动布局逻辑冲突,建议直接删掉这两行,让Auto Layout自动适配父视图的大小。 - 要是看不出约束问题,可以开启约束日志排查:在APP启动时加入下面的代码,控制台会输出约束冲突的详细信息:
UserDefaults.standard.set(true, forKey: "_UIConstraintBasedLayoutLogUnsatisfiable")
2. 规范视图控制器切换的代码逻辑
你当前直接在动画块里修改window.rootViewController,可能会导致旧VC的视图在动画过程中被提前释放,进而引发数组越界。试试用更符合UIKit规范的切换方式:
guard let window = UIApplication.shared.keyWindow else { return } guard let currentRootVC = window.rootViewController else { return } let storyboard = UIStoryboard(name: "Main", bundle: nil) let newVC = storyboard.instantiateViewController(withIdentifier: "MyViewControllerIdentifier") // 先把新VC作为子控制器加入当前根VC currentRootVC.addChild(newVC) newVC.view.frame = currentRootVC.view.bounds currentRootVC.view.addSubview(newVC.view) newVC.didMove(toParent: currentRootVC) // 执行切换动画 UIView.transition(with: window, duration: 0.3, options: .transitionCrossDissolve, animations: { currentRootVC.willMove(toParent: nil) currentRootVC.view.removeFromSuperview() currentRootVC.removeFromParent() window.rootViewController = newVC }, completion: { completed in print("切换完成") })
这种方式严格遵循了UIKit的视图控制器生命周期管理,能避免很多奇怪的崩溃。
3. 排查segue和目标VC的生命周期代码
既然segue切换也崩溃,说明问题不是切换方式的锅,得查目标VC内部:
- 先确认segue的identifier和目标VC的storyboard ID完全匹配,别打错字。
- 检查
MyViewController的viewDidLoad、viewWillAppear等生命周期方法里,有没有操作数组、字符串时越界的代码?比如访问array[index]但数组是空的,或者index超过了数组长度。 - 有没有自定义的视图(比如自定义TableView、CollectionView)?检查它们的数据源方法,比如
numberOfRowsInSection返回的数量和实际数据源数组的长度是否一致,这也是常见的越界原因。
4. 用异常断点精准定位问题
最直接的办法是给Xcode加个异常断点,这样崩溃时会直接停在引发错误的代码行:
- 打开Xcode的Breakpoint Navigator(快捷键
Cmd + 8) - 点击左下角的
+号,选择Exception Breakpoint... - 保持默认设置(Exception选All,Break选On Throw),点击Done
- 重新运行APP,崩溃时Xcode会带你找到具体哪一行代码出了问题,瞬间就能锁定根源!
内容的提问来源于stack exchange,提问作者Kurse
相关产品推荐
相关产品推荐

