LoginSignup
5
7

More than 5 years have passed since last update.

Swift 3.0 Firebase Databaseのコールバック関数

Posted at

Firebaseのデータベースを取得しているとき, 非同期処理が起こるのが問題

例えばこんな取得関数があったとして、

FirebaseController.swift
let ref = Database.database().reference()

        self.ref.observeSingleEvent(of: .value, with: { (snapshot) in
            for folder in snapshot.children {
                if let snap = folder as? DataSnapshot {
                    print(folder.name) // その1
                }
            }
                }) { (error) in
            print(error.localizedDescription)
        }

print(folder.name) // その2

*その1 が走っている間に、その2を先に読んでしまう! *

これを止めるには、コールバック関数を使おう!

この例ではNotificationCenterを使って見ました〜

// identifierを定義
let notificationName = Notification.Name("NotificationIdentifier")
// notificationを受け取るための登録
NotificationCenter.default.addObserver(self, selector: #selector(YourClassName.methodOfReceivedNotification), name: notificationName, object: nil)
// notificationを発信する。
NotificationCenter.default.post(name: notificationName, object: nil)
// notificationを止める。
NotificationCenter.default.removeObserver(self, name: notificationName, object: nil);

上記を
まずはDatabaseを読み取る先にNotificaiotonCenter.post()を乗っける

FirebaseController.swift
...
        self.ref.child(firebasePath).observeSingleEvent(of: .value, with: { (snapshot) in
            for folder in snapshot.children {
                if let snap = folder as? DataSnapshot {
                    print(folder.name)
                }
            }
        NotificationCenter.default.post(name: Notification.Name(rawValue:"FirebaseNotification"), object: nil)

        }) { (error) in
            print(error.localizedDescription)
        }
...

CollectionView等にデータを流す・見せるとしたら、読み込んだだけでは、表示が変わらないので、最後にReloadData()が必要だったりする。

ViewConreoller.swift


    @IBOutlet UICollectionView collectionView

    //ここで上記のFirebaseController.swiftを初期化している。データベースも呼んでいる
    var fbController = FirebaseController()

    override func viewDidLoad() {
        super.viewDidLoad()

        //observerをセットする:database initが終わるのを見守る関数
        NotificationCenter.default.addObserver(self, selector: #selector(self.initCompleted(notification:)), name: Notification.Name("FirebaseNotification"), object: nil)

        collectionView.register(CategoryCell.self,forCellWithReuseIdentifier: self.cellid)
        view.addSubview(collectionView)
    }


    func initCompleted(notification: Notification?) {

        // 読み終わったら、removeObserverをして,Obeserverを消す。
        NotificationCenter.default.removeObserver(self)
        refreshCollectionView()
    }

    //データが変更したら、reloadData()を呼ばないといけない。
    func refreshCollectionView() {
        self.collectionView?.reloadData()
    }

友達のミッチーが解決してくれました!ありがとう!!!
https://github.com/Nismit

5
7
6

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
7