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

SwiftUI中@State变量attachmentID无法保留值的问题求助

问题解决:SwiftUI中Sheet弹窗无法获取正确的attachmentID值

问题根源

你使用.sheet(isPresented:)绑定弹窗时,SwiftUI会在视图初始渲染阶段就创建好Sheet的内容,而非弹窗触发时才初始化。所以即便你在按钮点击时更新了attachmentID,Sheet内的AttachmentView拿到的始终是初始值0。

修复方案

改用.sheet(item:)绑定弹窗,它会在绑定的可选值变为非nil时触发弹窗,且每次都会重新初始化Sheet内容,确保拿到最新的ID值。具体修改步骤如下:

  1. 将attachmentID改为可选Int类型,初始值设为nil:
@State private var attachmentID: Int? = nil
  1. 删除原有的showAttachmentSheet变量,按钮点击时直接赋值attachmentID:
Button {
    attachmentID = file.id
    debugPrint(attachmentID)
} label: {
    TextAndImageCell(title: file.filename, imageName: "paperclip")
}
  1. 替换原.sheet(isPresented:)为.sheet(item:),在Sheet中使用解包后的ID:
.sheet(item: $attachmentID) { id in
    AttachmentView(attachmentID: id, ticketID: currentPost!.id)
}

额外建议:代码中currentPost!.id用了强制解包,容易引发崩溃,建议改成可选绑定:

if let currentPost = currentPost {
    // 原List、Sheet代码,ticketID使用currentPost.id
}

完整修改后的代码片段

struct PostView: View {
    @State private var attachmentID: Int? = nil
    @State private var showSheet = false // 补充原代码未定义的showSheet
    
    var currentPost: Post?
    
    var body: some View {
        if let currentPost = currentPost {
            List(firstPost.postscontents.reversed(), id:\.id) { post in
                Text(post.contents)

                if !post.attachment.isEmpty {
                    ForEach(post.attachment, id: \.id) { file in
                        HStack{
                            Spacer()
                            Button {
                                attachmentID = file.id
                                debugPrint(attachmentID)
                            } label: {
                                TextAndImageCell(title: file.filename, imageName: "paperclip")
                            }
                            .padding(.horizontal, 10)
                            .padding(.vertical, 4)
                            .background(.gray)
                            .clipShape(Capsule())
                            
                        }
                    }
                }
            }
            .listStyle(.inset)
            .listItemTint(.lightBlue)
        
            .sheet(item: $attachmentID) { id in
                AttachmentView(attachmentID: id, ticketID: currentPost.id)
            }
        }

        Button {
            showSheet = true
        } label: {
            Image(systemName: "plus.message.fill")
                .font(.system(size: 40))
                .padding()
        }
    }
}

// 让Int遵循Identifiable协议,适配sheet(item:)的要求
extension Int: Identifiable {
    public var id: Int { self }
}

若不想让Int遵循Identifiable,也可自定义包装结构体:

struct AttachmentIdentifier: Identifiable {
    let id: Int
}

随后将attachmentID改为@State private var attachmentID: AttachmentIdentifier? = nil,按钮点击时赋值attachmentID = AttachmentIdentifier(id: file.id),Sheet内使用id.id即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 16:28:30