Search code examples
iosswiftswift2ios9

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?


Solution

  • 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 {
    
        }
    }