Как загрузить изображение из Firebase в аватар пользователя

#swift #firebase #firebase-storage #dispatch-queue

#swift #firebase #firebase-хранилище #отправка-очередь

Вопрос:

У меня проблема с загрузкой изображений из firebase. У меня есть две функции. Один из них собирает информацию о пользователе, второй загружает изображение аватара пользователя. К сожалению, изображения загружаются после того, как функция создает нового пользователя. Я знаю, что это будет проблемой с асинхронностью Firebase, но я не знаю, как настроить DispatchQueue для правильной работы. Можете ли вы мне с этим помочь?

// функция, которая загружает изображение пользователя в класс user manager

 func loadUserImage(contactUserID: String, completion: @escaping (UIImage) -> Void) {
        let userID = Auth.auth().currentUser!.uid
        var userImageRef = self.storage.child("(userID)/userImage.jpg")
        var image = UIImage()

        if contactUserID != "" {
            userImageRef = self.storage.child("(contactUserID)/userImage.jpg")
        }
        userImageRef.getData(maxSize: 5 * 1024 * 1024) { (data, error) in
            if let error = error {
                print("Error with retrieving data: (error.localizedDescription)")
            } else {
                if data?.count != 0 {
                    image = UIImage(data: data!)!
                } else {
                    image = UIImage(systemName: "person.circle.fill")!
                }
                completion(image)
            }
        }
    }
 

// функция, которая загружает пользователя в класс диспетчера контактов

 func loadContactList(completion: @escaping ([User]) -> Void) {
    let currentUserID = Auth.auth().currentUser!.uid
    db.collection("contacts")
        .document(currentUserID)
        .collection("userContacts")
        .addSnapshotListener { (querySnapshot, error) in
            var contactList = [User]()
            if let error = error {
                print("Error with retrieving data from DB: (error.localizedDescription)")
            } else {
                if let snapshotDocuments = querySnapshot?.documents {
                    for document in snapshotDocuments {
                        let data = document.data()
                        let uid = data["uid"] as! String
                        let name = data["name"] as! String
                        let email = data["email"] as! String
                        var contact = User(email: email, name: name, userID: uid)

                        DispatchQueue.global().sync {
                            self.userService.loadUserImage(contactUserID: uid) { (image) in
                                contact.photoURL = image
                            }
                        }
                        contactList.append(contact)

                        contactList.sort {
                            $0.name < $1.name
                        }
                        completion(contactList)
                    }
                }
            }
        }
}
 

// Реализация функции в ViewController

 func loadContactList() {
    self.contactService.loadContactList { (contactArray) in
        self.contactList = contactArray
        self.tableView.reloadData()
    }
}
 

Ответ №1:

Что вы можете сделать, так это сохранить URL-адрес изображения в базе данных firebase и после этого создать это расширение:

 import UIKit

let imageCache: NSCache = NSCache<AnyObject, AnyObject>()

extension UIImageView {
    
    func loadImageUsingCacheWithUrlString(urlString: String) {
        
        self.image = nil
        
        if let cachedImage = imageCache.object(forKey: urlString as AnyObject) as? UIImage {
            self.image = cachedImage
            return
        }
        
        let url = URL(string: urlString)
        if let data = try? Data(contentsOf: url!) {
            
            DispatchQueue.main.async(execute: {
                
                if let downloadedImage = UIImage(data: data) {
                    imageCache.setObject(downloadedImage, forKey: urlString as AnyObject)
                    
                    self.image = downloadedImage
                }
            })
        }
    }
}
 

И вызовите:

 if let url = data["imgUrl"] as? String {
    self.myImageView.loadImageUsingCacheWithUrlString(urlString: url)
}
 

Для этого вам нужно создать и инициализировать UIImage объект. Если вы работаете с классами ячеек, вам необходимо создать этот объект в ячейке.