Xcode Organizer报Swift数组越界崩溃,求排查方案
问题分析与修复方案
核心原因
从崩溃日志可直接定位到崩溃发生在PageViewController.updateUIViewController方法中,访问context.coordinator.controllers[currentPage]时触发数组越界,根源在于:
- 数据不同步:
Coordinator的controllers数组仅在初始化时基于当时的pages生成,当外部传入的list(即pages的来源)元素数量减少时,controllers不会自动更新,而currentPage可能仍保持在原来的较大索引,导致currentPage >= controllers.count。 - 无边界校验:
updateUIViewController中直接使用currentPage访问数组,没有任何范围检查,一旦索引超出有效范围就会崩溃。
修复步骤
1. 同步控制器数组并添加边界校验
修改PageViewController的updateUIViewController方法,确保controllers始终与最新的pages一致,并对currentPage做安全处理:
func updateUIViewController(_ pageViewController: UIPageViewController, context: Context) { // 同步controllers数组,匹配最新的pages数量 if context.coordinator.controllers.count != pages.count { context.coordinator.controllers = pages.map { UIHostingController(rootView: $0) } } // 计算安全的当前页码,确保在有效范围内 let safePage = min(max(currentPage, 0), context.coordinator.controllers.count - 1) // 如果页码被修正,同步更新绑定的currentPage if safePage != currentPage { currentPage = safePage } // 仅当数组非空时执行页面切换 if !context.coordinator.controllers.isEmpty { pageViewController.setViewControllers( [context.coordinator.controllers[safePage]], direction: .forward, animated: true ) } }
2. 优化BannerView的页码切换逻辑
在nextPage方法中增加空数组判断,避免空数组时出现无效计算:
func nextPage() -> Void { guard !list.isEmpty else { return } currentPage = currentPage == list.count - 1 ? 0 : currentPage + 1 }
3. 处理空数组场景
在BannerView的body中,当list为空时返回占位视图,避免创建无意义的PageViewController:
var body: some View { Group { if list.isEmpty { // 替换为你需要的空状态占位视图 Text("暂无横幅内容") .frame(maxWidth: .infinity, maxHeight: .infinity) } else { ZStack(alignment: .bottom) { PageViewController( pages: list.map(BannerCard.init), currentPage: $currentPage, onChange: { timer?.invalidate() timer = nil restLoop() } ) PageControl(numberOfPages: list.count, currentPage: $currentPage) .frame(width: CGFloat(list.count * 18)) } .onAppear(perform: restLoop) } } }
额外建议
- 所有数组下标访问前都必须做边界校验,或使用
indices.contains(_:)判断索引有效性:if context.coordinator.controllers.indices.contains(currentPage) { // 安全访问数组元素 } - 避免在
Coordinator中缓存依赖外部可变数据的内容,尽量在updateUIViewController中保持数据最新。
内容的提问来源于stack exchange,提问作者Ethan Smith
相关产品推荐
相关产品推荐

