Firebase: закрытие в obvserve EventType и observeSingleEventOfType с блокировкой: не выполняется (со сборкой)

#ios #swift #firebase #firebase-realtime-database #firebase-authentication

#iOS #swift #firebase #firebase-realtime-database #firebase-аутентификацией

Вопрос:

Я не могу понять, почему databaseRef withBlock никогда не выполняется.

Я уже создал рабочее приложение для чата в реальном времени в Swift, и все работало так, как ожидалось, поэтому я не совсем новичок в этом…

Пользователь входит в LoginViewController с помощью авторизации в Facebook и перенаправляется в это основное представление. Твиты хранятся в базе данных Firebase.

Когда я устанавливаю точки останова и выполняю это, он переходит ко второму закрытию ошибки, дважды повторяет закрытие ошибки и затем переходит к инструкциям по сборке. (внизу сообщения)

Я пробовал различные способы вызова observeEventType и observeSingleEventOfType (что я и хотел бы сделать), и результат здесь всегда один и тот же.

Я распечатал все объекты на консоль, чтобы убедиться, что пользователь вошел в систему и с FirebaseAuth .

 import UIKit
import FirebaseAuth
import FirebaseDatabase

class MainViewController: UIViewController, UITableViewDataSource, UITableViewDelegate
{
    var loggedInUser = FIRAuth.auth()?.currentUser
    var loggedInUserDetails = AnyObject?()
    @IBOutlet weak var homeTableView: UITableView!

    var tweets = [AnyObject?]()

    override func viewDidLoad() {
        super.viewDidLoad()

        let databaseRef = FIRDatabase.database().referenceWithPath("user_profile/(self.loggedInUser!.uid)")

        print(self.loggedInUser!uid)  // Prints uid
        // get the logged in user -- POINT OF FAILURE
        databaseRef.observeSingleEventOfType(.Value, withBlock: {(snapshot) in

        //store the logged in user's details
        self.loggedInUserDetails = snapshot

        //get all the tweets by the user
        databaseRef.child("tweets/(self.loggedInUser!.uid)").observeEventType(.ChildAdded, withBlock: {(snapshot:FIRDataSnapshot) in

            self.tweets.append(snapshot)

            self.homeTableView.insertRowsAtIndexPaths([NSIndexPath(forRow:0, inSection: 0)], withRowAnimation: UITableViewRowAnimation.Automatic)

        }) {(error) in
            print(error.localizedDescription)
        }
    }) {(error) in
            print("Error 1")  // never prints
            print(error.localizedDescription)  //never prints
       }
}
  

Я также заметил, что при выполнении инструкций по сборке с помощью xcode он переходит к отмене обратного вызова.

Здесь он начинается (строка 1)

 0x10f5b3db8 < 36>: movq   %r12, -0x30(%rbp)
0x10f5b3dbc < 40>: movq   0x1a7a8d(%rip), %rax      ; (void *)0x000000010f762e70: FIRDatabaseReference
0x10f5b3dc3 < 47>: movq   %rax, -0x28(%rbp)
0x10f5b3dc7 < 51>: movq   0x19f39a(%rip), %rsi      ; "observeSingleEventOfType:withBlock:withCancelBlock:"
0x10f5b3dce < 58>: leaq   -0x30(%rbp), %rdi
  

Затем после нескольких переходов он выполняет эту инструкцию:

    0x10f5b874e < 291>: movq   0x19ef03(%rip), %rsi      ; "observeChildEventWithHandle:withCallbacks:cancelCallback:"
  

Комментарии:

1. Если код переходит к одному из замыканий с ошибкой, у вас, скорее всего, нет разрешения на чтение данных. error Будет содержать информацию о точной ошибке (например, в каком месте вы пытаетесь прочитать, на которое у вас нет разрешения).

2. Извините… Я забыл объяснить, что он никогда не выполняет код при закрытии ошибки. Я просто перехожу от ошибки к последней скобке, а затем возвращаюсь к ошибке. Есть ли другой способ найти ошибку? Я не видел никаких комментариев с ошибками в сборке.

3. Я проверил, чтобы подтвердить, что пользователь вошел в систему (в приведенном выше редактировании кода), и он распечатывает uid, как и ожидалось.

Ответ №1:

Возможно, вы получаете сообщение об ошибке.

 // get the logged in user -- POINT OF FAILURE
databaseRef.observeSingleEventOfType(.Value, withBlock: {(snapshot) in

    //store the logged in user's details
    self.loggedInUserDetails = snapshot

    //get all the tweets by the user
    databaseRef.child("tweets/(self.loggedInUser!.uid)").observeEventType(.ChildAdded, withBlock: {(snapshot:FIRDataSnapshot) in

        self.tweets.append(snapshot)

        self.homeTableView.insertRowsAtIndexPaths([NSIndexPath(forRow:0, inSection: 0)], withRowAnimation: UITableViewRowAnimation.Automatic)

    }) {(error) in
        print(error.localizedDescription)
    }
}) {(error) in
    print(error.localizedDescription) // maybe permission denied?
}
  

Комментарии:

1. Разве закрытие ошибки в конце не поймает это и не выведет его на консоль? При переходе через отладчик он проходит мимо последней скобки в withBlock

2. У вас есть вложенные наблюдатели, но вы обрабатываете только блок ошибок для внутреннего. Если observeSingleEventOfType наблюдение завершится неудачей, поскольку у вас нет блока ошибок, ничего не произойдет.

3. Ах … не заметил этого, но ошибки нет. Это довольно неприятно… Я дополнил код мелким шрифтом comb…it похоже, что эта единственная вещь решила не сработать. Возможно, это какая-то причуда в xcode..

Ответ №2:

В конце концов, это была не проблема с Xcode…проблема заключалась в том, что TableView (numberOfRowsInSection) возвращал неправильное количество строк, и это все портило.

Я узнал, что Firebase не всегда выполняет действия в том порядке, в котором вы ожидаете.

Как только я обнаружил проблему, я прошел через отладчик, и он вошел в viewDidLoad, нажал observeSingleEvent, а затем перешел к концу закрытия….как я и думал, проблема. Но затем он перешел к моей функции TableView()-> UITableView и начал выполнение, прежде чем вернуться к observeSingleEvent, для которого мы пытаемся получить данные.

Почти кажется, что закрытие Firebase выполняется лениво.

Если я узнаю больше об этой теме, я исправлю этот ответ.

Приветствия!