@Published变量更新但SwiftUI视图if/else未切换状态问题
问题描述
在FeedViewModel中定义了@Published类型的loading变量,用于控制FeedView切换加载视图与已加载视图。ViewModel初始化时设置loading = true以显示进度视图,预期从Firestore加载完数据后将其设为false,从而切换到已加载视图。但实际情况是,无论loading变量更新为true还是false,视图始终停留在初始状态:设置loading = true时一直显示LoadingView,设为false则一直显示LoadedView。
已尝试的解决方法包括:将DispatchQueue.main.asyncAfter移入Firestore请求闭包、移除DispatchQueue调用、改用视图内的State变量。打印结果显示loading的布尔值确实已变为false,但视图始终无法切换到else分支。且相同的加载/已加载逻辑在其他视图中可正常工作,仅在此视图失效。
FeedViewModel 代码
class FeedViewModel: ObservableObject { @Published var followingPosts = [Post]() @Published var posts = [Post]() @Published var loading = true let service = FeedService() init() { if self.followingPosts.isEmpty { fetchAllPosts() } else { fetchFollowingPosts() } } func fetchFollowingPosts() { guard let userid = Auth.auth().currentUser?.uid else { return } service.fetchFollowingPosts(forUid: userid) { posts in self.followingPosts = posts DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { self.loading = false } } } func fetchAllPosts() { service.fetchAllPosts { posts in self.posts = posts DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { self.loading = false } } } }
FeedView 代码
struct FeedView: View { @StateObject var viewModel = FeedViewModel() var body: some View { if viewModel.loading { LoadingView } else { LoadedView } } } extension FeedView { var LoadedView: some View { VStack (spacing: 0) { Image("logo") .resizable() .frame(width: 48, height: 54) ScrollView(.vertical, showsIndicators: false) { PullToRefresh(coordinateSpaceName: "pullToRefresh") { viewModel.fetchFollowingPosts() } if viewModel.followingPosts.isEmpty { Group { Divider() VStack (alignment: .leading, spacing: 12) { Image("wave") .renderingMode(.template) .resizable() .frame(width: 36, height: 36) .foregroundColor(.accentColor).opacity(0.25) Text("Welcome") .font(Font.headline) .foregroundColor(Color(.label)) } .padding() Divider() } LazyVStack(spacing: 24) { ForEach(viewModel.posts.shuffled().prefix(10), id: \.id) { post in FeedCell(viewModel: FeedCellViewModel(post: post)) } } } else { LazyVStack (spacing: 24) { ForEach(viewModel.followingPosts, id: \.id) { post in FeedCell(viewModel: FeedCellViewModel(post: post)) } } } } .coordinateSpace(name: "pullToRefresh") } } var LoadingView: some View { VStack (spacing: 24) { Image("logo") .resizable() .frame(width: 48, height: 54) Spacer() ProgressView() Spacer() } .frame(maxWidth: .infinity) } }
FeedService 代码
struct FeedService { func fetchFollowingPosts(forUid uid: String, completion: @escaping([Post]) -> Void) { var posts = [Post]() COLLECTION_FOLLOWING.document(uid).collection("user-following") .getDocuments { snapshot, _ in guard let documents = snapshot?.documents else { return } documents.forEach { doc in let userId = doc.documentID COLLECTION_POSTS.whereField("uid", isEqualTo: userId) .getDocuments { snapshot, _ in guard let documents = snapshot?.documents else { return } let post = documents.compactMap({ try? $0.data(as: Post.self) }) posts.append(contentsOf: post) completion(posts.sorted(by: { $0.timestamp.dateValue() > $1.timestamp.dateValue() })) } } } } func fetchAllPosts(completion: @escaping([Post]) -> Void) { COLLECTION_POSTS.getDocuments { snapshot, _ in guard let documents = snapshot?.documents else { return } let posts = documents.compactMap({ try? $0.data(as: Post.self) }) completion(posts) } } }
内容的提问来源于stack exchange,提问作者amelia
相关产品推荐
相关产品推荐

