由于获取状态,ProgressView 无限期运行

ProgressView runs indefinitely because of fetching state

提问人:Vader20FF 提问时间:10/28/2021 最后编辑:Vader20FF 更新时间:10/28/2021 访问量:58

问:

我在为ProfileViewModel显示ProfileView中的所有数据时遇到异步数据获取问题。 我尝试了很多方法,结果要么无限期地加载 ProgressView 要么出现 nil 错误。 首先,我设置了 sessionStore(身份验证状态),将其从 View 的 .onAppear 传递给 ViewModel。然后我想将 firstName 和用户名从 Firebase 获取到我的 ProfileViewModel,这是我在 ProfileView init 中执行的 fetchData 函数中执行的。

ProfileViewModel:

@MainActor
class ProfileViewModel: ObservableObject {
    @Published var sessionStore: SessionStore?
    private let firestoreManager = FirestoreManager()
    private let firebaseStorageManager = FirebaseStorageManager()
    
    @Published var profile: Profile?
    @Published var profilePicturePhotoURL: URL?
    
    @Published var workouts: [IntervalWorkout]?
    @Published var fetching: Bool = true
    
    init(forPreviews: Bool) {
        [...]
    }
    
    init() {
        [...]
        
        Task {
            try await fetchData()
        }
    }
    
    func setup(sessionStore: SessionStore) {
        self.sessionStore = sessionStore
    }
    
    func fetchData() async throws {
        if sessionStore != nil {
            if sessionStore!.currentUser != nil {
                    print("Fetching Data")
                    
                    let (firstname, username, birthDate, age, country, language, gender, email, profilePictureURL) = try await self.firestoreManager.fetchDataForProfileViewModel(userID: sessionStore!.currentUser!.uid)
                    
                    self.profile = Profile(id: sessionStore!.currentUser!.uid, firstName: firstname, username: username, birthDate: birthDate, age: age, country: country, language: language, gender: gender, email: email, profilePictureURL: profilePictureURL)
                    
                    print(self.profile!.firstName)
                    
                    if profilePictureURL != nil {
                        self.firebaseStorageManager.getDownloadURLForImage(stringURL: profilePictureURL!, userID: sessionStore!.currentUser!.uid) { photoURL in
                             self.profilePicturePhotoURL = photoURL
                            print("Data fetched")
                        }
                    } else {
                        print("Data fetched - no profilePicture")
                    }
                    
                    print("FETCHING: \(self.fetching)")
                    if self.profile != nil {
                        fetching = false
                    }
                
            } else {
                print("Data not fetched - no sessionStore.currentUser")
            }
        } else {
            print("Data not fetched - no sessionStore")
        }
    }
    
    func uploadPhoto(image: UIImage) {
        [...]
    }
    
    func emailAddressChange(oldEmailAddress: String, password: String, newEmailAddress: String, completion: @escaping (() -> ())) {
        [...]
    }
    
    func deleteUserData(completion: @escaping (() -> ())) {
        [...]
    }
}

配置文件视图:

struct ProfileView: View {
    @ObservedObject private var profileViewModel = ProfileViewModel()
    @EnvironmentObject private var sessionStore: SessionStore
    @Environment(\.colorScheme) var colorScheme
    
    @State private var image = UIImage()
    
    @State private var shouldPresentAddActionSheet = false
    @State private var shouldPresentImagePicker = false
    @State private var shouldPresentCamera = false
    
    @State private var shouldPresentSettings = false
    
    @State private var tabSelection = 0
    
    init(forPreviews: Bool) {
        if forPreviews {
            self.profileViewModel = ProfileViewModel(forPreviews: true)
        }
    }
    
    var body: some View {
        GeometryReader { geometry in
            let screenWidth = geometry.size.width
            let screenHeight = geometry.size.height
            
            if !self.profileViewModel.fetching {
                ScrollView(.vertical) {
                    HStack {
                        if profileViewModel.profilePicturePhotoURL != nil {
                            AsyncImage(url: profileViewModel.profilePicturePhotoURL!) { image in
                                [...]
                            } placeholder: {
                                [...]
                            }
                        } else {
                            [...]
                        }
                        
                        Spacer(minLength: screenWidth * 0.05)
                        
                        VStack {
                            HStack {
                                Text(profileViewModel.profile != nil ? profileViewModel.profile!.firstName : "Name")
                                    [...]
                                }
                            }
                            .padding(.top, screenHeight * 0.02)
                            
                            HStack {
                                Text(profileViewModel.profile != nil ? profileViewModel.profile!.username : "Username")
                                    .foregroundColor(Color(uiColor: UIColor.lightGray))
                                Spacer()
                            }
                            
                            Spacer()
                        }
                    }
                    .padding()
                    
                    [...]
                }
                [...]
            } else {
                VStack {
                    Spacer()
                    HStack {
                        Spacer()
                        ProgressView("Loading user's data")
                            .progressViewStyle(RingProgressViewStyle())
                        Spacer()
                    }
                    Spacer()
                }
            }
        }
        .onAppear {
            self.profileViewModel.setup(sessionStore: sessionStore)
        }
    }
}

控制台输出:

Data not fetched - no sessionStore
Data not fetched - no sessionStore
Fetching Data
Data not fetched - no sessionStore
Łukasz
Data fetched - no profilePicture
FETCHING: true
iOS Firebase SwiftUI null UIAgprogressView

评论

0赞 jnpdx 10/28/2021
你能把它简化成一个最小的可重复的例子吗?
0赞 Vader20FF 10/28/2021
@jnpdx老实说,我无能为力,因为我不完全知道问题出在哪里 - 是因为 sessionStore 或 ProfileViewModel 初始化,还是因为某处的数据分配问题。我把代码删减成一些部分,在我看来,这些部分必须由比我更有经验的人来检查
2赞 jnpdx 10/28/2021
这里肯定有一些不需要测试的部分(堆栈、文本元素、不必要的状态变量等)。它使它变得更加复杂,因为你通过到处添加 [...] 来使其不合规。尝试制作一些可以复制并粘贴到 Xcode 中的东西。这样做的过程也可能有助于隔离您的错误。
0赞 Vader20FF 10/30/2021
@jnpdx 在尝试进一步修剪代码时,我意识到我可以更好地描述我的问题,所以我创建了全新的问题,可以在这里找到:stackoverflow.com/questions/69772487/......

答: 暂无答案