Проверка, равен ли моментальный снимок Firebase нулю в Swift

Я пытаюсь запросить Firebase, чтобы проверить, есть ли какой-либо пользователь, у которого есть waiting: "1", а затем, когда снимок будет возвращен, я хочу увидеть, равен ли он нулю. Я попытался сделать это, но метод, который я использовал, не работает, и у меня есть какой-то вывод только в том случае, если снимок не равен нулю. Я добавил код, который у меня есть в настоящее время, и текст JSON из Firebase.

import UIKit
import Firebase
import Spring

class GamesViewController: UIViewController {

let ref = Firebase(url: "https://123test123.firebaseio.com")
var activityIndicator: UIActivityIndicatorView = UIActivityIndicatorView()   

@IBAction func StartGamePressed(sender: AnyObject) {
    print("test1")
    var peopleWaiting: [String] = []

    let userRef = Firebase(url:"https://123test123.firebaseio.com/users")
    userRef.queryOrderedByChild("waiting").queryEqualToValue("1")
        .observeEventType(.ChildAdded, withBlock: { snapshot in
            print(snapshot.key)
            if snapshot.key == nil {
                print("test2")
                let userData = ["waiting": "1"]
                let usersRef = self.ref.childByAppendingPath("users")
                let hopperRef = usersRef.childByAppendingPath("\(self.ref.authData.uid)")

                hopperRef.updateChildValues(userData, withCompletionBlock: {
                    (error:NSError?, ref:Firebase!) in
                    if (error != nil) {
                        print("Data could not be saved.")
                        self.displayAlert("Oops!", message: "We have been unable to get you into a game, check you have an internet conection. If this problem carries on contect support")
                    } else {
                        print("Data saved successfully!")
                        let storyboard = UIStoryboard(name: "Main", bundle: nil)
                        let Home : UIViewController = storyboard.instantiateViewControllerWithIdentifier("continueToGame")
                        self.presentViewController(Home, animated: true, completion: nil)

                    }

                })


            } else {
                var randomUID: String
                peopleWaiting.append(snapshot.key)
                let randomIndex = Int(arc4random_uniform(UInt32(peopleWaiting.count)))
                randomUID = peopleWaiting[randomIndex]
                print(randomUID)
                let storyboard = UIStoryboard(name: "Main", bundle: nil)
                let Home : UIViewController = storyboard.instantiateViewControllerWithIdentifier("continueToGame")
                self.presentViewController(Home, animated: true, completion: nil)

            }
        })
}

func displayAlert(title: String, message: String){

    let formEmpty = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.Alert)
    formEmpty.addAction((UIAlertAction(title: "Ok", style: .Default, handler: { (action) -> Void in

    })))

    self.presentViewController(formEmpty, animated: true, completion: nil)
}

func activityIndicatorFunction(){

    activityIndicator = UIActivityIndicatorView(frame: CGRectMake(0, 0, 100, 100))
    activityIndicator.backgroundColor = UIColor(red:0.16, green:0.17, blue:0.21, alpha:1)
    activityIndicator.layer.cornerRadius = 6
    activityIndicator.center = self.view.center
    activityIndicator.hidesWhenStopped = true
    activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.WhiteLarge
    view.addSubview(activityIndicator)
    activityIndicator.startAnimating()
    UIApplication.sharedApplication().beginIgnoringInteractionEvents()

}


}

JSON-данные:

{
"68e42b7f-aea5-4c3f-b655-51a99cb05bb0" : {
  "email" : "[email protected]",
  "username" : "test1",
  "waiting" : "0"
},
"8503d5a8-fc4a-492b-9883-ec3664898b4f" : {
  "email" : "[email protected]",
  "username" : "test2",
  "waiting" : "0"
}
}

person Tom Fox    schedule 28.02.2016    source источник
comment
Вероятный ответ ниже. Но, пожалуйста, прочтите о проблеме XY (потому что я думаю, что ваш вопрос мог быть связан с тем, как определить, существует ли определенный дочерний элемент?) и о том, как создать минимальный, полный, проверяемый пример. Если вы позаботитесь об обоих, нам будет намного легче вам помочь.   -  person Frank van Puffelen    schedule 29.02.2016


Ответы (2)


Здесь происходит несколько вещей, но самая важная из них заключается в том, что вы не можете проверить наличие детей с .ChildAdded. Это имеет смысл, если подумать: событие .ChildAdded возникает, когда в местоположение добавляется дочерний элемент. Если дочерний элемент не добавлен, событие не будет вызвано.

Поэтому, если вы хотите проверить, существует ли ребенок в данном месте, вам нужно использовать .Value. Как только вы это сделаете, появятся различные способы обнаружения существования. Вот один:

ref.queryOrderedByChild("waiting").queryEqualToValue("1")
   .observeEventType(.Value, withBlock: { snapshot in
       print(snapshot.value)
       if !snapshot.exists() {
           print("test2")
       }
   });
person Frank van Puffelen    schedule 29.02.2016

Проверьте наличие NSNull. Это код для наблюдения за узлом. Запросы работают примерно так же.

Вот полное и протестированное приложение. Чтобы использовать, измените строку «существующий» на какой-то путь, который, как вы знаете, существует, например, путь вашего пользователя, а «несуществующий» на какой-то несуществующий путь.

    let myRootRef = Firebase(url:"https://your-app.firebaseio.com")
    let existingRef = myRootRef.childByAppendingPath("existing")
    let notExistingRef = myRootRef.childByAppendingPath("notexisting")

    existingRef.observeEventType(.Value, withBlock: { snapshot in

        if snapshot.value is NSNull {
            print("This path was null!")
        } else {
            print("This path exists")
        }

    })

    notExistingRef.observeEventType(.Value, withBlock: { snapshot in

        if snapshot.value is NSNull {
            print("This path was null!")
        } else {
            print("This path exists")
        }

    })

Обратите внимание, что при использовании .Value будет гарантировано возвращаемый результат, и блок всегда будет срабатывать. Если в вашем коде используется .ChildAdded, то блок будет срабатывать только при наличии дочернего элемента.

Также проверьте, как ваши данные отображаются в firebase.

users
   user_0
     waiting: 1

если отличается от

users
   user_0
     waiting: "1"

Обратите внимание, что «1» — это не то же самое, что 1.

person Jay    schedule 28.02.2016
comment
Это точно работает! Я обновил свой ответ полным и протестированным приложением для копирования и вставки, которое я только что написал. Если ваш код не работает, значит, что-то еще не так - NSNull - это то, что вам нужно! - person Jay; 28.02.2016
comment
Ну, все, что я знаю, это то, что мой запрос, похоже, не работает, хотя запрос, который вы используете, отличается от моего ... может ли это иметь значение? @Джей - person Tom Fox; 28.02.2016
comment
Если ваша ссылка или запрос искажены или приложение настроено неправильно, это может вызвать всевозможные проблемы. Я бы предложил скопировать и вставить ваш код в качестве метода тестирования и удалить все, кроме самого необходимого, и пройтись по вашему коду, чтобы увидеть, где он не работает. - person Jay; 28.02.2016
comment
Я знаю, что запрос, который я использую, работает нормально, потому что, если есть результат для возврата запроса, он работает, и код работает отлично, но если его нет, ничего не происходит ... @Jay - person Tom Fox; 28.02.2016
comment
@Jay Я считаю, что транзакции Firebase могут возвращать нулевой снимок. Мы передаем в блок транзакций не снимок, а текущее значение. Это текущее значение действительно может быть нулевым. Но вы не используете здесь транзакции, так что это не имеет значения. - person Frank van Puffelen; 28.02.2016
comment
Я не думаю, что nil против NSNull здесь важная часть. Проблема в OP заключается в том, что он использует .ChildAdded, который будет срабатывать только когда существует дочерний элемент. Ваш подход с использованием .Value является правильным для этого варианта использования. - person Frank van Puffelen; 29.02.2016
comment
@FrankvanPuffelen Да! У вас есть правильный ответ. Я оставлю свой для примера кода проверки NSNull, поскольку они идут рука об руку. - person Jay; 29.02.2016
comment
@Jay, как я могу использовать логический оператор НЕ в этом операторе if? if snapshot.value is NSNull. Я хотел бы написать if snapshot.value !== NSNull { //} , но он не компилируется. Спасибо - person bibscy; 11.02.2018
comment
@bibscy попробуйте if !(snapshot.value равно NSNull) - person Jay; 11.02.2018
comment
@ Джей, не могли бы вы помочь мне с этим? stackoverflow.com/questions/49013963 - person bibscy; 27.02.2018