SwiftUI中fullScreenCover弹出空白视图问题求助
问题描述
我正在开发首个基于SwiftUI的全栈应用,尝试从处理用户登录的LoginView跳转至处理新用户数据输入的DataInputView,但弹出的fullScreenCover完全空白。我是Swift新手,代码可能存在不规范之处。已排查并发问题、Firebase数据存储及认证功能均正常,无报错信息,但无法解决该问题。
相关代码:
// UserMetaDataViewModel.swift import Foundation import FirebaseAuth import FirebaseFirestore import UIKit import FirebaseStorage @MainActor class UserMetaDataViewModel: ObservableObject, Identifiable { @Published var userMetaData: UserMetaData init(userMetaData: UserMetaData = UserMetaData(id: "", email: "", nameFirst: "", nameLast: "", handle: "", gender: Gender.other, age: 0, bio: "", dataInputComplete: false)) { self.userMetaData = userMetaData } func saveUserData(userMetaData: UserMetaData) async -> String? { let db = Firestore.firestore() if let id = userMetaData.id { do { try await db.collection("userMetaData").document(id).setData(userMetaData.dictionary) print("Success in saving data for user \(userMetaData.nameFirst)") return nil } catch { print("Error could not update data in 'userMetaData'") return error.localizedDescription } } else { print("Error could not create a new instance of UserMetaData: UID is nil") return "User ID is nil" } } func loadUserData() async -> Bool { let db = Firestore.firestore() guard let userID = Auth.auth().currentUser?.uid else { return false } do { let document = try await db.collection("userMetaData").document(userID).getDocument() print("Document data: \(String(describing: document.data()))") if document.exists { do { let loadedUserData = try document.data(as: UserMetaData.self) self.userMetaData = loadedUserData return true } catch { print("Error decoding user data: \(error)") return false } } else { print("Document not found") return false } } catch { print("Error loading user data: \(error.localizedDescription)") return false } } func saveProfilePic(userMetaData: UserMetaData, image: UIImage) async -> Bool { guard let userEmail = userMetaData.email else { print("error finding ID of userMetaData") return false } let photoName = UUID().uuidString let storage = Storage.storage() let storageRef = storage.reference().child("\(userEmail)/\(photoName).jpeg") guard let resizedImage = image.jpegData(compressionQuality: 0.2) else { print("Error, could not resize image") return false } let metadata = StorageMetadata() metadata.contentType = "image/jpg" var imageURLString = "" do { let _ = try await storageRef.putDataAsync(resizedImage, metadata: metadata) do { let imageURL = try await storageRef.downloadURL() imageURLString = "\(imageURL)" } catch { print("Error: could not get ImageUrl after saving profile URL") } print("profile image saved") } catch { print("Error uploading image to firebase storage") return false } let db = Firestore.firestore() let collectionString = "email/\(userEmail)/profilePic" return true } } // DataInputView.swift import SwiftUI struct DataInputView: View { @ObservedObject var userMetaDataVM: UserMetaDataViewModel var body: some View { Form { Section(header: Text("Enter Information")) { TextField("First", text: $userMetaDataVM.userMetaData.nameFirst) TextField("First", text: $userMetaDataVM.userMetaData.nameLast) TextField("Handle", text: $userMetaDataVM.userMetaData.handle) Picker("Gender", selection: $userMetaDataVM.userMetaData.gender) { ForEach(Gender.allCases, id: \.self) { Text($0.rawValue) } } TextField("Age", value: $userMetaDataVM.userMetaData.age, formatter: NumberFormatter()) TextField("Bio", text: $userMetaDataVM.userMetaData.bio) } Button(action: { Task { if let email = userMetaDataVM.userMetaData.email { _ = await userMetaDataVM.saveUserData(userMetaData: userMetaDataVM.userMetaData) } } }) { Text("Continue") } } } } struct SwiftUIView_Previews: PreviewProvider { static var previews: some View { DataInputView(userMetaDataVM: UserMetaDataViewModel(userMetaData: UserMetaData(id: "", email: "", nameFirst: "", nameLast: "", handle: "", gender: Gender(rawValue: "") ?? Gender.male, age: 10, bio: "", profilePictureURL: "", dataInputComplete: false))) } }
解决方向
1. 修正fullScreenCover的触发与ViewModel传递
父视图LoginView中需用@StateObject持有ViewModel实例,确保生命周期正确,再传递给DataInputView:
struct LoginView: View { @State private var showDataInput = false @StateObject private var metaDataVM = UserMetaDataViewModel() var body: some View { Button("登录") { // 登录逻辑完成后触发 showDataInput = true } .fullScreenCover(isPresented: $showDataInput) { DataInputView(userMetaDataVM: metaDataVM) } } }
2. 删除重复的ViewModel定义
你提供的代码里重复定义了UserMetaDataViewModel,这会导致编译异常或逻辑混乱,必须删除其中一份。
3. 确保UserMetaData属性为可变类型
检查UserMetaData结构体,所有需要绑定的属性必须是var而非let:
struct UserMetaData: Identifiable, Codable { var id: String var email: String? var nameFirst: String var nameLast: String var handle: String var gender: Gender var age: Int var bio: String var profilePictureURL: String var dataInputComplete: Bool // 编码为字典的逻辑 var dictionary: [String: Any] { return [ "id": id, "email": email ?? "", "nameFirst": nameFirst, "nameLast": nameLast, "handle": handle, "gender": gender.rawValue, "age": age, "bio": bio, "profilePictureURL": profilePictureURL, "dataInputComplete": dataInputComplete ] } }
4. 完善Gender枚举实现
确保枚举遵循CaseIterable和RawRepresentable,保证Picker正常渲染:
enum Gender: String, CaseIterable { case male = "Male" case female = "Female" case other = "Other" }
5. 调试视图渲染
在DataInputView中添加测试文本,确认视图是否被加载:
struct DataInputView: View { @ObservedObject var userMetaDataVM: UserMetaDataViewModel var body: some View { VStack { Text("数据输入页") Form { // 原有表单内容 } } } }
如果测试文本显示,问题出在表单绑定逻辑;若仍空白,需检查ViewModel传递或fullScreenCover触发逻辑。
内容的提问来源于stack exchange,提问作者Dune Guy
相关产品推荐
相关产品推荐

