下载 Firebase 存储数据时,DispatchGroup 未正确执行

Posted

技术标签:

【中文标题】下载 Firebase 存储数据时,DispatchGroup 未正确执行【英文标题】:DispatchGroup is not executing correctly when downloading Firebase Storage Data 【发布时间】:2021-11-07 02:08:08 【问题描述】:

我有一个从 Firebase 获取用户数据的闭包,在其中我有另一个从 Firebase 存储下载图像的闭包。

在用户登录之前,我需要能够从存储中下载图像。我想我会尝试一个 DispatchGroup(),但我无法将图像数据分配给 self.photoImage,它总是返回 nil。

self.photoImage = UIImage(data: data!)

这是我第一次使用 Storage 和 GroupDispatch(),因此我们将不胜感激。

相关代码:

class AppViewModel: ObservableObject 
    private var db = Firestore.firestore()
    
    @Published var userInfo: User?
    @Published var signedIn: Bool = false
    
    var handle: AuthStateDidChangeListenerHandle?
    let authRef = Auth.auth()
    
    var authHandle : AuthStateDidChangeListenerHandle?
    var rootInfoCollection : CollectionReference!
    var userIdRef = ""

    var photoImage: UIImage?
    var downloadImageTask: StorageReference?
    
    var group = DispatchGroup()
    
    func fetchUserData()
        db.collection("Users").document("\(userIdRef)").getDocument  [self] document, error in
            // Check for error
            if error == nil 
                // Check that this document exists
                if document != nil && document!.exists 
                                        
                    self.userInfo = document.map  (documentSnapshot) -> User in
                        let data = documentSnapshot.data()
                        
                        let uid = data?["uid"] as? UUID ?? UUID()
                        let company = data?["company"] as? String ?? ""
                        let name = data?["name"] as? String ?? ""
                        let admin = data?["admin"] as? Bool ?? false
                        let photoRef = data?["photoRef"] as? String ?? ""
                        
                        self.downloadImageTask = Storage.storage().reference().child(photoRef)
                        
                        return User(uid: uid, company: company, name: name, admin: admin, photoRef: photoRef, photoImage: nil)
                    
                    
                    group.enter()
                    downloadImageTask?.getData(maxSize: 6 * 1024 * 1024)  data, error in
                        if let error = error 
                            print("Got an error fetching data: \(error.localizedDescription)")
                            return
                         else 
                            self.photoImage = UIImage(data: data!)
                        
                        self.group.leave()
                    
                    
                    DispatchQueue.global(qos: .default).async 
                        
                        self.group.wait()
                        
                        DispatchQueue.main.async 
                            
                            if photoImage != nil 
                                print("Photo Image Is Set")
                            
                            
                            withAnimation 
                                self.signedIn = true
                            
                        
                    
                    
                    
                    
                
            
        
    

【问题讨论】:

你的 DispatchGroup 的整个结构是错误的,无论如何这不是 DispatchGroup 合适或需要的情况。 我建议你去读一些关于 GCD 的东西,Ray Wenderlich 的教程很不错raywenderlich.com/… 【参考方案1】:

虽然我没有测试过,但也许这对你有用:

class AppViewModel: ObservableObject 

    private var db = Firestore.firestore()

    @Published var userInfo: User?
    @Published var signedIn: Bool = false

    var handle: AuthStateDidChangeListenerHandle?
    let authRef = Auth.auth()

    var authHandle : AuthStateDidChangeListenerHandle?
    var rootInfoCollection : CollectionReference!
    var userIdRef = ""

    var photoImage: UIImage?
    var downloadImageTask: StorageReference?

    var group = DispatchGroup()

    func fetchUserData()
        db.collection("Users").document("\(userIdRef)").getDocument  [self] document, error in
            // Check for error
            if error == nil 
                // Check that this document exists
                if document != nil && document!.exists 
                                    
                    self.userInfo = document.map  (documentSnapshot) -> User in
                        let data = documentSnapshot.data()
                    
                        let uid = data?["uid"] as? UUID ?? UUID()
                        let company = data?["company"] as? String ?? ""
                        let name = data?["name"] as? String ?? ""
                        let admin = data?["admin"] as? Bool ?? false
                        let photoRef = data?["photoRef"] as? String ?? ""
                    
                        self.downloadImageTask = Storage.storage().reference().child(photoRef)
                    
                        return User(uid: uid, company: company, name: name, admin: admin, photoRef: photoRef, photoImage: nil)
                    
                
                    group.enter()
                    downloadImageTask?.getData(maxSize: 6 * 1024 * 1024)  data, error in
                        if let error = error 
                            print("Got an error fetching data: \(error.localizedDescription)")
                            return
                         else 
                            self.photoImage = UIImage(data: data!)
                        
                        self.group.leave()
                    
                    group.notify(queue: .main)  [self] in
                        if photoImage != nil 
                            print("Photo Image Is Set")
                        
                        
                        withAnimation 
                            self.signedIn = true
                        
                    
                
            
        
    

【讨论】:

以上是关于下载 Firebase 存储数据时,DispatchGroup 未正确执行的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Firebase 存储下载 URL 中删除查询字符串

从Android中的firebase下载多个文件时如何管理内存

如何将多个图像上传到 Firebase 存储并返回多个下载 URL

从多个文件上传 Firebase 存储中获取下载 url

将图像批量导入 Firebase 存储并将下载链接添加到 Firebase 数据库节点

使用 Cloud Functions 的下载 URL 从 Firebase 存储中删除文件