SwiftUI中ChatView无法显示,始终出现ProgressView问题求助
问题原因与解决方案
你的问题出在fullScreenCover的isPresented绑定和chatUser的状态更新不同步:当你在sheet的回调里设置chatUser后立刻切换shouldNavigateToChatView,SwiftUI可能还没完成chatUser的状态更新,fullScreenCover就已经开始渲染,导致第一个if let分支没命中,最终显示ProgressView。
修复方案:改用item绑定替代isPresented
用fullScreenCover(item:)绑定可选的导航目标,SwiftUI会自动检测可选值的变化,确保状态同步后再渲染对应视图。
步骤1:定义导航目标枚举
先创建一个枚举来区分两种导航场景,同时实现Identifiable协议(item绑定要求遵循该协议):
enum ChatNavigationTarget: Identifiable { case user(User) case chat(ChatModel) var id: String { switch self { case .user(let user): return user.id case .chat(let chat): return chat.id // 确保ChatModel有id属性 } } }
步骤2:替换原有状态变量
把原来的chatUser、chatForView、shouldNavigateToChatView替换成一个枚举类型的状态变量:
@State private var navigationTarget: ChatNavigationTarget?
步骤3:修改触发导航的逻辑
- 聊天列表单元格点击事件:
ChatListCell(chat: chat) .onTapGesture { navigationTarget = .chat(chat) }
- 新建聊天选择用户后的回调:
ChatCreationView(didSelectUser: { user in print("did select user \(user)") navigationTarget = .user(user) })
步骤4:更新fullScreenCover绑定
替换原来的isPresented绑定为item绑定,通过switch匹配不同场景:
.fullScreenCover(item: $navigationTarget) { target in switch target { case .user(let user): ChatView(oppUser: user) case .chat(let chat): ChatView(chat: chat) } }
完整修改后的代码
enum ChatNavigationTarget: Identifiable { case user(User) case chat(ChatModel) var id: String { switch self { case .user(let user): return user.id case .chat(let chat): return chat.id } } } struct ChatListView: View { @State private var shouldShowChatCreationScreen = false @State private var navigationTarget: ChatNavigationTarget? @ObservedObject private var viewModel = ChatListViewModel() var body: some View { NavigationView { ScrollView { ForEach(viewModel.chats) { chat in ChatListCell(chat: chat) .onTapGesture { navigationTarget = .chat(chat) } } } .navigationTitle("Chats") .toolbar { ToolbarItem(placement: .navigationBarTrailing) { Button(action: { shouldShowChatCreationScreen.toggle() }) { Image(systemName: "square.and.pencil") } } } .sheet(isPresented: $shouldShowChatCreationScreen) { ChatCreationView(didSelectUser: { user in print("did select user \(user)") navigationTarget = .user(user) }) } .fullScreenCover(item: $navigationTarget) { target in switch target { case .user(let user): ChatView(oppUser: user) case .chat(let chat): ChatView(chat: chat) } } } } }
这样修改后,状态更新会被SwiftUI正确捕获,再也不会出现状态不同步导致的ProgressView问题。
内容的提问来源于stack exchange,提问作者Icon45
相关产品推荐
相关产品推荐

