Ваша проблема в том, что вы пытаетесь получить доступ к переменной, значение которой на самом деле зависит от обработчика завершения внутри нее.
Поэтому приложение дает вам nil иногда , когда обработчик завершения не сработал, с другой стороны, при отладке вы можете увидеть значение, потому что значение теперь существует, но проблемаЭто компилятор теперь может читать другие строки кода, и он не знает, что значение теперь здесь.
Другими словами: вы пытаетесь получить доступ к некоторому значению, которое вы извлекаете откуда-то, и пока вы ждете, чтобы это значение вернулось и правильно его использовали, компилятор теперь читает что-то другое в другом потоке.,
Что вам не хватает, так это обработчик завершения, который фактически запускает значение этой переменной, когда оно исходит из того места, где вы ее выбираете, поэтому вынуждает компилятор возвращаться и читать его, когда он срабатывает.
Примечание: Я рекомендую прочитать эту статью о обработчиках завершения и о том, как они на самом деле функционируют в swift.
Как исправить ваш случай:
Поскольку вы используете enum
, и вам нужна функция извлечения внутри самой переменной, по какой-то причине вы можете исправить это, только создав критическую секцию.с DispatchSemaphores
.
Я создал небольшую демонстрацию для вас, чтобы понять, как она работает, и я также рекомендую эту статью.
Демо:
var name: String {
let semaphore = DispatchSemaphore(value: 0)
var name = "no value"
DispatchQueue.global().asyncAfter(deadline: .now() + 2.0) {
name = "new Value"
semaphore.signal()
}
semaphore.wait()
return name
}
Ваш код должен быть примерно таким.
var name: String {
let semaphore = DispatchSemaphore(value: 0)
var name:String?
let uid = Auth.auth().currentUser?.uid
Database.database().reference().child("users").child(uid!).observeSingleEvent(of: .value, with: { (snapshot) in
if let dictionary = snapshot.value as? [String:AnyObject] {
name = dictionary["firstName"] as? String
print(String(describing: name))
semaphore.signal() // signal when i get the new value
}
}, withCancel: nil)
semaphore.wait() // wait till signal
return name ?? "Does not Work"
}
Остерегайтесь, это единственный способ для вашего случая, и он не рекомендуется, я рекомендую изменить вашу структуру, потому что вы будете замораживать приложение, пока не получите данные, и этоэто плохо.