#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
объект. Если вы работаете с классами ячеек, вам необходимо создать этот объект в ячейке.