You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ViewController间导航后展示BottomSheet触发CALayer NaN崩溃求助

问题分析与解决方案

问题场景

两个UIViewController(ViewControllerA、ViewControllerB)均实现了点击按钮展示BottomSheet的功能。当从ViewControllerA导航到ViewControllerB后,在ViewControllerB中触发BottomSheet展示时,应用崩溃,报错:

CALayer position contains NaN: [nan 438.667]

单独打开任一ViewController,或ViewControllerA未展示BottomSheet时导航到B,均不会触发该崩溃。已尝试在viewWillDisappear中关闭BottomSheet、给BottomSheet设置固定高度,问题仍未解决。

可能的崩溃原因

  1. BottomSheet实例复用导致视图层次冲突:两个VC共用同一个BottomSheet实例,导航后该实例的父视图引用未正确更新,布局计算时出现非法数值。
  2. 布局计算依赖未初始化/非法视图属性:BottomSheet的位置或高度计算依赖了未完成布局的视图属性(如未加载内容的UIScrollView.contentSize),导致计算出NaN值。
  3. 导航过程中BottomSheet图层未正确清理:ViewControllerA中的BottomSheet虽已关闭,但图层引用未完全释放,与ViewControllerB的视图层次产生冲突,引发布局计算异常。

解决方案

1. 每个VC持有独立的BottomSheet实例

禁止全局或跨VC复用同一个BottomSheet对象,在每个ViewController内部单独初始化:

// ViewControllerA中实现
class ViewControllerA: UIViewController {
    private var bottomSheet: BottomSheetViewController?
    
    func showBottomSheet() {
        bottomSheet = BottomSheetViewController()
        // 配置并展示BottomSheet
        present(bottomSheet!, animated: true)
    }
    
    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        // 彻底销毁引用,避免残留
        bottomSheet = nil
    }
}

// ViewControllerB中执行相同逻辑,单独初始化BottomSheet

2. 展示前强制完成父视图布局

在展示BottomSheet前,先触发当前VC视图的布局更新,确保所有视图frame已正确计算:

func showBottomSheet() {
    view.layoutIfNeeded() // 强制完成当前视图布局
    let bottomSheet = BottomSheetViewController()
    // 基于当前视图尺寸设置BottomSheet的内容大小
    bottomSheet.preferredContentSize = CGSize(width: view.bounds.width, height: 300)
    present(bottomSheet, animated: true)
}

3. 排查布局约束中的非法计算

检查BottomSheet内部的布局代码,规避可能产生NaN的逻辑:

  • 不要直接用scrollView.contentSize.height作为高度约束,若scrollView未加载内容,改用子视图的intrinsicContentSize或设置默认高度。
  • 确保所有约束的乘数、常量均为合法数值,避免除以0等操作。

4. 调试定位NaN来源

在崩溃前打印BottomSheet的关键属性,定位问题环节:

func showBottomSheet() {
    let bottomSheet = BottomSheetViewController()
    // 打印调试信息,排查异常数值
    print("BottomSheet frame: \(bottomSheet.view.frame)")
    print("BottomSheet layer position: \(bottomSheet.view.layer.position)")
    present(bottomSheet, animated: true)
}

根据日志找到产生NaN的具体属性,针对性修复计算逻辑。

内容的提问来源于stack exchange,提问作者Firda Sahidi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 12:02:57