Brandon Deo
Brandon Deo

Reputation: 4305

Swift Scoping Rules -- nil value after setting a non-nil value

I'm writing a DataService that interfaces with Firebase. I'm setting self.realID within a closure and when I reference it outside the closure, it fails because it unwraps a nil value. Why is this happening?

My file:

import Foundation
import Firebase

class Database {

    var firebaseRef = Firebase(url:"https://<<UNIQUE>>.firebaseio.com")

    class var sharedInstance: Database {
        struct Data {
            static var instance: Database?
            static var token: dispatch_once_t = 0
        }

        dispatch_once(&Data.token) {
            Data.instance = Database()
        }

        return Data.instance!
    }

    var uid : String!

    var realID : String!

    var validated = false

    func validate(user: String, study: String) -> Bool {

        firebaseRef.authUser(user+"@example.com", password: user,
             withCompletionBlock: { error, authData in
                if error != nil {
                    NSLog(String(error))
                } else {
                    self.uid = authData.uid
                    NSLog(authData.uid)
                }
        })

        let usersRef = Firebase(url: "https://<<UNIQUE>>.firebaseio.com/users")
        usersRef.observeEventType(FEventType.Value, withBlock: { (snapshot) in
            let value = snapshot.value.objectForKey("study") as! String
            self.realID = value
            NSLog(self.realID) // this is a non-nil value
        })

        NSLog("About to encounter nil value and crash")
        if self.realID == study {
            return true
        }
        return false
    }
}

How do i prevent this fatal error from happening?

Upvotes: 0

Views: 93

Answers (1)

Rahul Katariya
Rahul Katariya

Reputation: 3628

You need to add a completionHandler because it is async request. If you will set the break points then return is executed before you are setting the id.

func validate(user: String, study: String, completionHandler:(Bool) -> Void) {

    let usersRef = Firebase(url: "https://<<UNIQUE>>.firebaseio.com/users")
    usersRef.observeEventType(FEventType.Value, withBlock: { (snapshot) in
        if let value = snapshot.value.objectForKey("study") as? String {
            self.realID = value
            completionHandler(true)
        } else {
            completionHandler(false)
        }
    })

}

UPDATE

validate("Rahul", study: "Study") { (value: Bool) in
    if value {

    } else {

    }
}

Upvotes: 5

Related Questions