Я создаю экземпляр класса User
с помощью Firebase DataSnapshot.При вызове инициализатора init(snapshot: DataSnapshot)
он должен асинхронно извлекать значения из двух ссылок на базу данных, а именно pictureRef
и nameRef
, через обработчики завершения @escaping методов getFirebasePictureURL
и getFirebaseNameString
(используя метод observeSingleEvent
Firebase),Ссылки pictureRef
и nameRef
являются потомками одного родительского узла.Однако при создании экземпляра класса он никогда не инициализирует свойства имени и изображения User
класса, поскольку init
выполняется синхронно.
import Firebase
class User {
var uid: String
var fullName: String? = ""
var pictureURL: URL? = URL(string: "initial")
//DataSnapshot Initializer
init(snapshot: DataSnapshot) {
self.uid = snapshot.key
getFirebasePictureURL(userId: uid) { (url) in
self.getFirebaseNameString(userId: self.uid) { (fullName) in
self.fullName = fullName
self.profilePictureURL = url
}
}
func getFirebasePictureURL(userId: String, completion: @escaping (_ url: URL) -> Void) {
let currentUserId = userId
//Firebase database picture reference
let pictureRef = Database.database().reference(withPath: "pictureChildPath")
pictureRef.observeSingleEvent(of: .value, with: { snapshot in
//Picture url string
let pictureString = snapshot.value as! String
//Completion handler (escaping)
completion(URL(string: pictureString)!)
})
}
func getFirebaseNameString(userId: String, completion: @escaping (_ fullName: String) -> Void) {
let currentUserId = userId
//Firebase database name reference
let nameRef = Database.database().reference(withPath: "nameChildPath")
nameRef.observeSingleEvent(of: .value, with: { snapshot in
let fullName = snapshot.value as? String
//Completion handler (escaping)
completion(fullName!)
})
}
}
В предыдущем посте *1016* было высказано предположение, чтоЯ добавляю обработчик завершения @escaping к методу init
:
init(snapshot: DataSnapshot, completionHandler: @escaping (User) -> Void) {
self.uid = snapshot.key
getFirebasePictureURL(userId: uid) { (url) in
self.getFirebaseNameString(userId: self.uid) { (fullName) in
self.fullName = fullName
self.profilePictureURL = url
completionHandler(self)
}
}
}
Однако для этого потребуется, если я инициализирую этот класс с помощью User(snapshot: snapshot)
в методе вне этого класса, который инкапсулирует телоэтого метода в обработчике завершения метода User
init, который не будет работать для моего текущего проекта.
Есть ли способ использовать группы диспетчеризации для приостановки выполнения в главном потоке до fullName
и pictureURL
заполнены значениями?Или есть альтернативный способ сделать это?