Переменная доступа в закрытии Firebase

У меня есть следующий запрос Firebase, в котором я проверяю, существует ли уже имя пользователя в базе данных. Я хотел бы присвоить логическое значение (true) переменной с именем usernameAlreadyExists. Однако мне нужно получить доступ к этой переменной с ее новым значением вне замыкания. Я читал, что мне нужно реализовать завершениеHandler или обратный вызов, чтобы сделать это. Однако я не знаю, как реализовать это в синтаксисе запроса Firebase:

var usernameAlreadyExists = false

FIRDatabase.database().reference().child("usernames").queryOrderedByValue().queryEqual(toValue: self.username.text).queryLimited(toFirst: 1).observe(.childAdded, with: { snapshot in

        // Username unavailable, chose another one
        self.invalidUsernameMsg.text = "This username already exists, please choose another one."
        print(snapshot)
        print(snapshot.value)
        usernameAlreadyExists = true

})

print(usernameAlreadyExists)

print(usernameAlreadyExists) --> Я хочу, чтобы эта строка выводила "true", но она печатает "false", потому что приведенный выше код выполняется асинхронно.

Любая помощь более чем приветствуется. Благодарю вас!


person ayarem502    schedule 08.02.2017    source источник


Ответы (1)


Вы видите значение false, когда печатаете свою переменную userNameAlreadyExists, просто потому, что вы правы. Программа будет выполнять ваш код очень быстро, включая печать, а затем, когда Firebase завершит свой запрос, она добавит изменение значения вашего userNameAlreadyExists на true.

Это понятно?

Кроме того, для обработчика обратного вызова или завершения у вас уже есть это в вашем коде Firebase. Часть snapshot in — это начало вашего обработчика завершения.

Если вы хотите напечатать свою переменную в true, поместите ее в обработчик завершения, например:

var usernameAlreadyExists = false

FIRDatabase.database().reference().child("usernames").queryOrderedByValue().queryEqual(toValue: self.username.text).queryLimited(toFirst: 1).observe(.childAdded, with: { snapshot in

        // Username unavailable, chose another one
        self.invalidUsernameMsg.text = "This username already exists, please choose another one."
        print(snapshot)
        print(snapshot.value)
        usernameAlreadyExists = true
        print(usernameAlreadyExists)
})

РЕДАКТИРОВАТЬ: OP хочет проверить имя пользователя, существует ли оно перед регистрацией.

  1. Определять, когда пользователь перестает вводить текст внутри текстового поля имени пользователя. /3231194

  2. Внутри функции, обнаруженной выше, поместите используемую вами функцию Firebase в свой вопрос, например:

    func userDidStopTypingUsername() {
        // Firebase query here.
        // Then if existing, do something and store the value too in your bool variable.
    }
    
  3. Кроме того, внутри вашего IBAction или функции кнопки «Регистрация» также подтвердите userNameAlreadyExists. Если существует, то сделайте что-нибудь и вернитесь, чтобы предотвратить переход к регистрации. В противном случае продолжайте.

person Glenn Posadas    schedule 08.02.2017
comment
Большое спасибо за разъяснения Prettyitgirl.com! Однако мне нужно будет получить доступ к этой переменной вне замыкания. Я представил это с помощью print() в текущем примере только для того, чтобы отразить поведение кода. Но позже мне нужно будет использовать измененное значение (с false на true) переменной в моем коде. Мне нужно будет запустить некоторый код в зависимости от значения переменной, например: if usernameAlreadyExists { // Сделайте что-нибудь } else { // Сделайте что-нибудь еще }. Есть ли способ для меня сделать это? Спасибо еще раз! - person ayarem502; 08.02.2017
comment
Здравствуйте, я предполагаю, что вы выполняете эту проверку usernames для своей регистрации, верно? Или вы хотите сразу проверить имя пользователя, как только пользователь закончит или перестанет вводить текстовое поле? - person Glenn Posadas; 08.02.2017
comment
Это правильно. Я хочу проверить имя пользователя до того, как пользователь зарегистрируется. Идея состоит в том, что информация о пользователе будет записана в базу данных в конце процесса регистрации. Таким образом, если пользователь убьет приложение в середине процесса регистрации, никакие данные не будут записаны в БД. Приведенный выше код позволяет мне определить, занято ли уже имя пользователя в режиме реального времени. Однако мне нужен способ проверить, не занято ли имя пользователя, и, насколько я знаю, вы не можете сделать это с запросом Firebase, поэтому я хочу получить результат запроса выше и использовать его в качестве ссылки . - person ayarem502; 08.02.2017
comment
Эй, пожалуйста, проверьте мой отредактированный ответ. Посмотрите, не это ли вы пытаетесь сделать. - person Glenn Posadas; 08.02.2017
comment
Моя проблема в том, что значение userAlreadyExists, которое я должен проверить на 3-м шаге вашего ответа, всегда равно false независимо от существования того же имени пользователя в БД. или нет. Другими словами, когда я устанавливаю для userAlreadyExists значение true в запросе Firebase, у меня есть доступ к этому true значению userAlreadyExists< /b> только в этом запросе Firebase, поэтому весь код, в котором я хочу использовать userAlreadyExists, должен находиться в этом запросе Firebase. Мне нужно иметь возможность использовать true значение userAlreadyExists вне запроса (нужен обратный вызов). Спасибо - person ayarem502; 09.02.2017