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