私の主な質問は、ちらつきを取り除く方法ですが、私が正規化されていないFirebaseデータを正確かつ効率的に扱っているかどうかを知りたいだけです。私のアプローチは正しかったところにありますか?新しいFirebaseデータがTableViewセルのちらつき(Firebase/iOS/Swift)
私は、正規化されていないデータを持つfirebaseデータベースのデータを正しく表示しようとしています。私は投稿を持っていて、それぞれの投稿に関連したコメントをしています。誰かがviewcontrollerから新しいviewcontrollerにsegueingすることによって誰かが投稿のコメントセクションを開くたびに、投稿のユニークキー(postKey)を取得し、postCommentGroupに含まれるpostKeyに関連付けられたコメントのグループをスキャンします。 postCommentGroup内の各postKeyの子であるコメントのグループは、キーとしてのcommentKeyと値としての「true」であり、どのコメントがどの投稿に関連付けられているかを示します。コメントはまったく別のブランチにありますが、それはFirebaseのドキュメントによると思います。
本質的に3層のネストされたオブザーバがあります。
わかりやすくするために、私はテーブルビューでデキュー可能なセルを使ってセルをリサイクルしています。また、物を妨害しているかもしれない初歩的な遅延ロード/イメージキャッシュメカニズムもありますが、複雑なテーブルビューなので、それは問題だとは思わない。
知識が不足しているため、このサイクルを経る以外の方法でデータを表示する方法がわかりません。私はこのサイクルがちらつきを引き起こしていると思うが、データをロードする方法が他に何か分からない。私は、クエリを使用するなど、さまざまなやり方で試してみましたが、それを動作させることはできませんでした。
私は、データのクエリ方法(私が助けてくれるかもしれないと思う)を上手く取ろうとしましたが、Swiftの構文とFirebaseのアップデートを更新しました。これまでの例を少し難しくしています。
最近の FirebaseのサイトやGithubのいずれかのFirebaseのドキュメントでは、非正規化されたデータをやや複雑な方法で適切に使用した例はありません。誰でもSwift 3.0とFirebase(最新バージョン - 旧バージョンではない)を使用して非正規化データを扱うことに関して、GitHub上のプロジェクトであろうと、ブログであろうと、 stackoverflowの有用な記事?ここで
"comments" : {
"-KaEl8IRyIxRbYlGqyXC" : {
"description" : "1",
"likes" : 1,
"postID" : "-KaEfosaXYQzvPX5WggB",
"profileImageUrl" : "https://firebasestorage.googleapis.com",
"timePosted" : 1484175742269,
"userID" : "9yhij9cBhJTmRTexsRfKRrnmDRQ2",
"username" : "HouseOfPaine"
}
},
"postCommentGroup" : {
"-KaEfosaXYQzvPX5WggB" : {
"-KaEl8IRyIxRbYlGqyXC" : true,
"-KaEl9HiPCmInE0aJH_f" : true,
"-KaF817rRpAd2zSCeQ-M" : true
},
"-KaF9ZxAekTEBtFgdB_5" : {
"-KaFEcXsSJyJwvlW1w2u" : true
},
"-KaJyENJFkYxCffctymL" : {
"-KaQYa0d08D7ZBirz5B4" : true
}
},
"posts" : {
"-KaEfosaXYQzvPX5WggB" : {
"caption" : "Test",
"comments" : 11,
"imageUrl" : "https://firebasestorage.googleapis.com/",
"likes" : 0,
"profileImageUrl" : "https://firebasestorage.googleapis.com/",
"timePosted" : 1484174347995,
"title" : "test",
"user" : "17lIDKNx6LgzQmaeQ2ING582zi43",
"username" : "Freedom"
}
},
func commentGroupObserver() {
DataService.ds.REF_POST_COMMENT_GROUP.observeSingleEvent(of: .value, with: { (snapshot) in
if snapshot.value != nil {
if let snapshots = snapshot.children.allObjects as? [FIRDataSnapshot] , snapshots.count > 0 {
self.comments = []
for snap in snapshots {
if let tempVarPostKeyForCommentGroup = snap.key as String? {
if tempVarPostKeyForCommentGroup == self.post.postKey {
self.postKeyForCommentGroup = tempVarPostKeyForCommentGroup
self.commentObservers()
} else {
}
} else {
}
}
}
} else {
print("error")
}
})
}
func commentObservers() {
if postKeyForCommentGroup != nil {
constantHandle = DataService.ds.REF_POST_COMMENT_GROUP.child(postKeyForCommentGroup).observe(.value, with: { (snapshot) in
if snapshot.value != nil {
if let snapshots = snapshot.children.allObjects as? [FIRDataSnapshot], snapshots.count > 0
{
self.comments = []
for snap in snapshots {
if let theCommentIDForEachComment = snap.key as String? {
DataService.ds.REF_COMMENTS.child(theCommentIDForEachComment).queryOrdered(byChild: "timePosted").observeSingleEvent(of: .value, with: { (snapshots) in
if let commentDict = snapshots.value as? Dictionary<String, AnyObject> {
let key = snapshots.key
let comment = Comment(commentKey: key, dictionary: commentDict)
self.comments.insert(comment, at: 0)
}
self.tableView.reloadData()
})
}
}
}
} else {
}
})
} else {
}
}
UPDATE:私はどのように考え出し
クエリと以前のstackoverflowの記事で概説したデリゲートパターンを使用します。
getting data out of a closure that retrieves data from firebase
しかし、私は正しくデリゲートパターンを使用していた場合、私は知りません。
コードはクエリを使用して簡略化されていますが、依然として点滅しています。たぶん私はデリゲートパターンを正しく使用していないでしょうか?
func commentGroupObserver() {
DataService.ds.REF_POST_COMMENT_GROUP.queryOrderedByKey().queryStarting(atValue: post.postKey).queryEnding(atValue: post.postKey).observeSingleEvent(of: .value, with: { (snapshot) in
self.postKeyForCommentGroup = self.post.postKey
self.commentObservers()
})
}
func commentObservers() {
if postKeyForCommentGroup != nil {
constantHandle = DataService.ds.REF_POST_COMMENT_GROUP.child(postKeyForCommentGroup).observe(.value, with: { (snapshot) in
if snapshot.value != nil {
if let snapshots = snapshot.children.allObjects as? [FIRDataSnapshot]
{
self.comments = []
for snap in snapshots {
if let theCommentIDForEachComment = snap.key as String? {
DataService.ds.REF_COMMENTS.child(theCommentIDForEachComment).queryOrdered(byChild: "timePosted").observe(.value, with: { (snapshots) in
if let commentDict = snapshots.value as? Dictionary<String, AnyObject> {
let key = snapshots.key
let comment = Comment(commentKey: key, dictionary: commentDict)
self.comments.insert(comment, at: 0)
}
self.didFetchData(comments: self.comments)
})
}
}
}
} else {
}
})
} else {
}
}
func didFetchData(comments data:[Comment]){
self.tableView.reloadData()
}
}
とプロトコル
protocol MyDelegate{
func didFetchData(comments:[Comment]) }
それを解決した私の最後のコード:ジェイの提案の際
私は不要postCommentGroupを排除し、単にUIDを照会コメントがコメントの下にある投稿の投稿:
func commentObservers() {
let queryRef = DataService.ds.REF_COMMENTS.queryOrdered(byChild: "postID").queryEqual(toValue: self.post.postKey)
queryRef.observe(.value, with: { snapshot in
if let snapshots = snapshot.children.allObjects as? [FIRDataSnapshot] {
for snap in snapshots {
if let commentDict = snap.value as? Dictionary<String, AnyObject> {
let key = snap.key
let comment = Comment(commentKey: key, dictionary: commentDict)
self.comments.insert(comment, at: 0)
}
}
}
self.tableView.reloadData()
})
}
データ構造の画像を削除し、テキストデータに置き換えてください。そうすれば、コピー&ペーストが可能で検索が可能です。 JSON構造をエクスポートするには、Firebaseコンソールとデータベースに移動し、ウィンドウ内の右隅にある「3つの垂直方向の点」から「JSONの書き出し」を選択します。 – Jay
.valueを使用して一度読み取ると、同じデータをすべて.childAddedでもう一度読み込んでいるときに、データを二重に読み込んで(ちらつきを引き起こす)可能性があります。しかし、それはそうではありません - 知るべき質問には十分なコードがありません。 – Jay
イメージを削除し、編集したバージョンのデータ(JSON構造)をアップロードしました。私は、この質問を見るかもしれない人々に混乱していたので、childAddedで2番目の観測を削除しました。私はこれまで、データをロードするさまざまな方法をテストするためにこれを追加しました。 childAddedでの2回目の観察の削除は、ちらつきには何の影響もなく、追加する前に点滅していました。 – jasonhdev