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

SwiftUI删除List单元格后点击其他单元格无法弹出Sheet视图问题求助

问题根因

你代码的核心问题是StoriesSheet枚举的Identifiable协议实现不符合预期:

  • 当前你只为不同枚举类型返回了固定整数id,所有同类型的枚举实例(比如关联不同Story的showStory)id完全相同。
  • SwiftUI的sheet(item:)修饰符完全依赖item的id判断是否需要触发弹出动作。执行删除操作后列表数据源变更会触发视图重绘,此时如果新赋值的currentSheet和历史值id相同,系统会判定状态没有变化,不会触发sheet弹出。
修复方案

1. 修正StoriesSheet的id实现

调整id生成逻辑,将关联值的唯一标识纳入计算,保证每个枚举实例的id唯一(假设你的Story模型有id属性,没有的话可以用hashValue代替):

enum StoriesSheet: Identifiable {
    var id: String {
        switch self {
        case .showStory(let story):
            return "showStory_\(story.id)"
        case .addStory(let data):
            return "addStory_\(data.hashValue)"
        case .capturePicture(let type):
            return "capturePicture_\(type.hashValue)"
        case .editStory(let story):
            return "editStory_\(story.id)"
        case .report(let story):
            return "report_\(story.id)"
        }
    }
    
    case addStory(data: Data)
    case capturePicture(_ type: CaptureImageType)
    case showStory(_ story: Story)
    case editStory(_ story: Story)
    case report(_ story: Story)
}

2. 可选优化:调整sheet修饰符位置

你当前把sheet(item:)挂在列表内部的Group上,列表刷新时内层视图重绘可能导致修饰符状态丢失,建议移到外层的RefreshableList上:

var body: some View {
    RefreshableList(showRefreshView: $showRefreshView, pullStatus: $pullStatus, action: {
        viewModel.apply(.onRefresh)
    }, showRefreshOnBottom: $showRefreshOnBottom) {
        Group {
            if viewModel.shouldShowStories {
                storiesList() .padding(.bottom, 80)
                    .listRowInsets(EdgeInsets())
            } else {
                EmptyFeedView(imageName: "camera", description: "new_story_description", buttonText: "new_story") {
                    showGetPictureActionSheet = true
                }.frame(minWidth: 0, maxWidth: .infinity, minHeight: 500, maxHeight: .infinity, alignment: .center)
                .padding()
            }
        }
        // 移除原来这里的sheet修饰符
    }
    // 移到外层
    .sheet(item: $currentSheet, content: { sheet in
        getContent(for: sheet)
    })
    .onAppear {
        viewModel.apply(.onRefresh)
    }
    // 剩下的修饰符保持不变
}

3. 冗余代码清理(可选)

getContent方法中不需要额外判断viewModel.selectedStory,直接使用sheet参数传入的关联值即可,避免两个数据源不一致导致的异常:

private func getContent(for sheet: StoriesSheet) -> some View {
    switch sheet {
    case .showStory(let story):
        // 直接用参数里的story,不需要判断viewModel.selectedStory
        return AnyView(StoryDetailView(story: story))
    // 其他case保持不变
    }
}

内容的提问来源于stack exchange,提问作者Pradumna Patil

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 17:36:02