-1

In an attempt to implement MVVM into my project, I have moved out a Firebase code structure to a repository. I then want to return an array from that Firebaseloop back to the class the Firebase code previously resided (MyCollectionViewClass).

Declared above viewDidLoad:

var imageArray = [Recipe]()

In viewDidLoad:

imageArray = firebaseReference!.getFirebaseData(dataRecieverStringCollectionView: 
(self.dataRecieverStringCollectionView as? String)!)

firebaseReference!.getFirebaseDatais a reference to the repository class and its function.

self.dataRecieverStringCollectionViewis a string value passed into the function (I have checked so that it indeed contains the proper string value)

I have tried a number of different wrapping/unwrapping combinations without success. The error I'm getting is Unexpectedly found nil while unwrapping an Optional value Everything worked fine before, so it's just this code transition that has messed up the project.

The actual Firebase code in the repository class looks like this:

func getFirebaseData(dataRecieverStringCollectionView: String) -> Array<Recipe>{
    databaseRef = Database.database().reference()             
    storageRef = Storage.storage().reference()

databaseRef!.child(dataRecieverStringCollectionView).observeSingleEvent(of: .value, with: {(snapshot) in
        for item in snapshot.children.allObjects as! [DataSnapshot] {
            let thisItem = item.value as! NSDictionary

            let tempRecipe = Recipe()
            tempRecipe.fbKey = item.key
            tempRecipe.recipeImageObject = (thisItem["recipeImageFirebase"] as! String)
            tempRecipe.recipeHeaderObject = (thisItem["recipeHeaderFirebase"] as! String)
            tempRecipe.recipeTextObject = (thisItem["recipeIngredientsTextFirebase"] as! String)

            self.imageArray.append(tempRecipe)
        }
    })
    return imageArray
}

Not really sure what the issue is. I return a [Recipe] and try to store it in a [Recipe] variable in the class calling the method. Is the return type wrong in the function? Something else I've missed? Thanks in advance! :)

Doug Stevenson
  • 236,239
  • 27
  • 275
  • 302
Joakim Sjöstedt
  • 406
  • 1
  • 5
  • 13
  • You cannot return a value from a method that calls asynchronous code if the value is generated _in_ the asynchronous code. That would require time to run backwards, and that won't happen any time soon. — This is the single most commonly asked question on SO about asynchronous code. You could at least have tried searching before using more bandwidth on it. – matt Feb 16 '18 at 16:54

1 Answers1

1

The Firebase Realtime Database API is asynchronous. This means that methods like observeSingleEvent() return immediately when called, and the callback you provide to it is called some time later when the data is available. There are no guarantees about how long it will take to receive data.

In your code, you're returning imageArray before it gets populated by the data in the callback. You're basically trying to make an asynchronous API synchronous, which is not really a good idea. If you want to wrap asynchronous RTDB methods in a function, that function should also be synchronous.

Please read this blog for more information about why Firebase APIs are asynchronous and what to expect from them.

Doug Stevenson
  • 236,239
  • 27
  • 275
  • 302
  • Awesome! Thanks a lot for the info! :) – Joakim Sjöstedt Feb 16 '18 at 17:15
  • As I understand it from the blog, firebase already handles the code asynchronously (it loops the data in the background and goes on with the rest of the code), meaning that it can be run on the main thread without disturbing performance. Does that mean that I should keep the firebase code in the main thread and not move it into a repository à MVVM? – Joakim Sjöstedt Feb 16 '18 at 22:02
  • All your code is on the main thread. It's just being executed in a different order than how it appears. I don't have any advice about MVVM. All I can tell you is that you can't make the call synchronous. You should design for that, in whatever way your preferred framework allows. – Doug Stevenson Feb 16 '18 at 22:08