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

SwiftUI处理弹窗最后一个邀请时出现Index Out Of Range崩溃如何解决

崩溃根因分析

你遇到的崩溃确实是状态不同步导致的,使用PageTabViewStyle的TabView存在SwiftUI已知实现缺陷:当绑定的ForEach数据源数组突然变为空时,内部依赖的UICollectionView会触发索引越界崩溃。你当前代码中独立维护的sheetCount和groupHubVM.pendingInviteViewModels是两套独立状态,执行顺序的不确定性会导致数组先被清空、sheetCount还未更新的时间差出现,此时TabView渲染空数据源直接触发崩溃。


优化方案

核心思路是消除重复状态,所有逻辑唯一依赖pendingInviteViewModels数据源,同时加空状态保护避免TabView触底崩溃:

  1. 移除独立维护的sheetCount状态,从根源避免状态不同步
  2. 增加空数据源占位,数组为空时不渲染TabView
  3. 用onChange监听数据源数量,为空时自动关闭弹窗

修改后完整代码

PendingGroupsSheet 实现
struct PendingGroupsSheet: View {
    @ObservedObject var groupHubVM: GroupHubViewModel
    @Environment(\.presentationMode) var presentationMode

    init(groupHubVM: GroupHubViewModel) {
        self.groupHubVM = groupHubVM
    }

    var body: some View {
        // 空数据源保护:数组为空时渲染透明占位,直接触发关闭
        if groupHubVM.pendingInviteViewModels.isEmpty {
            Color.clear
                .onAppear {
                    presentationMode.wrappedValue.dismiss()
                }
        } else {
            TabView {
                ForEach(groupHubVM.pendingInviteViewModels) { singleGroupVM in
                    PendingGroupInviteView(
                        singleGroupVM: singleGroupVM,
                        onAcceptDecline: {} // 无需手动计数,交给监听逻辑处理
                    )
                }
            }
            .tabViewStyle(PageTabViewStyle())
            // 自动监听数据源变化,为空时立即关闭弹窗
            .onChange(of: groupHubVM.pendingInviteViewModels.count) { newCount in
                if newCount == 0 {
                    presentationMode.wrappedValue.dismiss()
                }
            }
        }
    }
}
按钮逻辑优化(可选,进一步降低崩溃概率)

如果你的邀请处理是同步操作,可以调整执行顺序,处理最后一个邀请时优先关闭弹窗,再修改数据源,彻底避免TabView渲染空数组:

Button(action: {
    let isLast = groupHubVM.pendingInviteViewModels.count == 1
    if isLast {
        presentationMode.wrappedValue.dismiss()
    }
    do {
        try singleGroupVM.declineGroupInvitation()
    } catch {
        print(error.localizedDescription)
    }
}){
    Text("Decline")
}
.buttonStyle(RoundedRectangleBlackButtonStyle())
.padding()

使用该优化时,需要将presentationMode或者关闭回调传入PendingGroupInviteView即可。


内容的提问来源于stack exchange,提问作者Charlie Page

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 02:45:02