Sergio Charles
Sergio Charles

Reputation: 379

Initializing class asynchronously with Firebase async observeSingleEvent methods' completion handlers

I am instantiating a User class via a Firebase DataSnapshot. Upon calling the initializer init(snapshot: DataSnapshot), I would like to asynchronously retrieve values from two distinct database references, namely pictureRef and nameRef, via the getFirebasePictureURL and getFirebaseNameString methods' @escaping completion handlers (using Firebase's observeSingleEvent method). However, console gives me two errors: 'self' captured by a closure before all members were initialized and 'self' used in method call 'getFirebasePictureURL' before all stored properties are initialized:

import Firebase

class User {

 var uid: String
 var fullname: String
 var pictureURL: URL

//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!)

        })
     }
  }

I am not too sure how I should initialize this asynchronously if this is the case.

Any help would be much appreciated!

Upvotes: 1

Views: 295

Answers (1)

Prashant Tukadiya
Prashant Tukadiya

Reputation: 16456

Class can not be initialized until its all stored property initialized with default value or property should be optional or property value assigned in init function called Designated Initializers

Designated initializers are the primary initializers for a class. A designated initializer fully initializes all properties introduced by that class and calls an appropriate superclass initializer to continue the initialization process up the superclass chain.

read this for more info. https://docs.swift.org/swift-book/LanguageGuide/Initialization.html

So in your case you are trying fullname and pictureURL as stored property though your escaping closure (Async task) task which is not allowed because it is not fulfil the rule

As I mentioned earlier you have following options

  1. Assign some default value
  2. Use optional value (best option you can handle error by checking optional later)

Hopefully it will helpful

Upvotes: 2

Related Questions