macOS Ventura下首次点击列表无法正常显示Sheet内容求助
问题分析与解决方案
问题原因
你的代码核心问题在于使用isPresented绑定控制Sheet显示,同时依赖selectedPerson状态提供Sheet内容——SwiftUI的状态更新是异步的,首次点击时Sheet会在selectedPerson完成赋值前就完成初始化,导致显示空内容;再次点击同一列表项时,selectedPerson未发生变化(仍是同一个对象),Sheet的内容视图不会重新渲染,因此依旧显示空。iOS控制台的重复present提示、macOS上的关闭动画异常,都是这种绑定方式导致的Sheet生命周期管理混乱。
修复代码
将isPresented绑定替换为item绑定,直接把selectedPerson作为Sheet的触发源,Sheet的显示/隐藏会自动跟随selectedPerson的nil状态,且每次selectedPerson变化时都会重新创建内容视图:
import SwiftUI struct Person: Identifiable { let id = UUID() var name: String var phoneNumber: String } struct ContactCard: View { var person: Person var body: some View { VStack { Image(systemName: "person") .font(.title) Text("\(person.name)") .font(.headline) } .padding() } } struct ContentView: View { var staff = [ Person(name: "Juan Chavez", phoneNumber: "(408) 555-4301"), Person(name: "Mei Chen", phoneNumber: "(919) 555-2481") ] @State var selectedPerson: Person? = nil var body: some View { List { ForEach(staff) { person in Text(person.name) .onTapGesture { selectedPerson = person } } // 使用item绑定替代isPresented,自动关联选中对象与Sheet状态 .sheet(item: $selectedPerson) { person in ContactCard(person: person) .onTapGesture { selectedPerson = nil } } } .padding() } }
额外说明
- 此方式无需额外的
showModal状态,selectedPerson的nil状态直接控制Sheet的显示/隐藏,逻辑更简洁。 - 每次
selectedPerson从nil变为非nil(包括切换到不同的Person对象),Sheet都会重新初始化内容视图,彻底解决首次点击空内容、重复点击同一项无响应的问题。 - 同时能修复iOS上的重复present警告,以及macOS上关闭Sheet时的动画异常,因为
item绑定会正确管理Sheet的生命周期。 - 你的原项目在iOS正常是因为老版本SwiftUI对
isPresented的状态同步处理与新版本存在差异,而macOS Ventura下SwiftUI的状态更新逻辑更严格,因此暴露了问题。
内容的提问来源于stack exchange,提问作者Subcreation
相关产品推荐
相关产品推荐

