2017-09-19 4 views
0

Firebaseからユーザーの "投稿"(画像とその説明)を読み込もうとしています。すべてが最初は正常に動作していて、viewControllerには3つの投稿が表示されますが、Firebaseに新しい画像をアップロードすると、ユーザーのすべての投稿の数が増え、アプリは4つではなく8つの投稿を読み込みます。なぜこうなった?Swift Firebaseが画像を何度も読み込んでいます

はここに私のスナップショット

Snap (qUJAq6aeNGYUeSsl9RmzldNpTME3) { 
"508D22DE-E865-460E-A011-A9170E0AB6A8" =  { 
    description = n; 
    downloadURL = "https://firebasestorage.googleapis.com/v0/b/findit-2f6eb.appspot.com/o/images%2F1A18AFAD-815C-417C-8C7A-226343FD0256.jpg?alt=media&token=46a6c929-a5ec-49e4-b6ca-aca896618fe0"; 
}; 
"D8434D58-1193-421D-8DFE-982983CB20D4" =  { 
    description = Maaa; 
    downloadURL = "https://firebasestorage.googleapis.com/v0/b/findit-2f6eb.appspot.com/o/images%2F059C91E8-95A8-44C6-9779-F678E2B9E033.jpg?alt=media&token=46ff5654-abec-49dc-bbb8-afae0eb6f1bd"; 
}; 
"F0E47F44-AE22-4D80-B173-E2168CB20B94" =  { 
    description = 7; 
    downloadURL = "https://firebasestorage.googleapis.com/v0/b/findit-2f6eb.appspot.com/o/images%2F1EA82DCA-FFE2-4B79-931C-28B66C7729AB.jpg?alt=media&token=8eaa2e02-5af8-4b43-adf2-2ac9214f902e"; 
}; 
} 

MyPostsTableViewControllerだ

import UIKit 

import Firebase 



    class MyPostsTableViewController: UITableViewController { 
let user = Userr() 
var downloadURL = "" 



var desCription = "" 
var allPosts = [String]() 
let currUser = Auth.auth().currentUser?.uid 

override func viewDidLoad() { 
    super.viewDidLoad() 



    let ref = Database.database().reference().child("posts").child(currUser!) 
    ref.observe(.value, with: { (snapshot) in 

     print(snapshot) 

     let dictionary = snapshot.value as! [String: Any] 
     var keys = Array(dictionary.keys) 
     self.allPosts = keys 

     for index in 0...(keys.count - 1) { 
      self.allPosts.removeAll() 
      self.user.descriptions.removeAll() 
      self.user.downloadUrls.removeAll() 
     ref.child(keys[index]).child("description").observe(.value, with: { (snapshot) in 
      ref.child(keys[index]).child("downloadURL").observe(.value, with: { (snapshot2) in 
       self.user.descriptions.append(snapshot.value as! String) 
       self.user.downloadUrls.append(snapshot2.value as! String) 

       self.tableView.reloadData() 

      }) 
     }) 


     } 

    }) 


} 




override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
    // #warning Incomplete implementation, return the number of rows 



     return user.descriptions.count 

} 


override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as!MyPostsTableViewCell 



    // print("downloadUrls Count \(user.downloadUrls.count)") 


    cell.descriptionLabel.text = user.descriptions[indexPath.row] 

    let profileImageURL = user.downloadUrls[indexPath.row] 

    cell.imageVieeew.contentMode = .scaleAspectFit 

    cell.imageVieeew.loadImageUsingCacheWithUrlString(profileImageURL) 



    return cell 

} 



} 

PostViewController

import UIKit 
    import Firebase 


class PostViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate { 

let user = Userr() 

@IBOutlet var textField: UITextField! 
@IBAction func postToServer(_ sender: Any) { 

     self.user.allow = false 
    // successfully authenticated user 
    if imageViw.image != nil && textField.text != ""{ 

     let imageName = NSUUID().uuidString 
     let postName = NSUUID().uuidString 
     let imagesFolder = Storage.storage().reference().child("images") 

     if let imageData = UIImageJPEGRepresentation(imageViw.image!, 0.2){ 
      imagesFolder.child("\(imageName).jpg").putData(imageData, metadata: nil, completion:{ 
       (metadata, error) in 

       if let error = error{ 
        self.presentAlert(alert: error.localizedDescription) 
       } else{ 
        if let downloadURL = metadata?.downloadURL()?.absoluteString { 

         let currUser = Auth.auth().currentUser?.uid 
         let ref = Database.database().reference().child("posts").child(currUser!).child(postName) 
         ref.child("downloadURL").setValue(downloadURL) 
         ref.child("description").setValue(self.textField.text!) 

        } 
       } 

      }) 


      } 

    } 
    else { 
     // we're missing something 
     presentAlert(alert: "You mus provide an image and a message for your post.") 
    } 


} 
+1

「子供を追加しました」を追加すると、firebaseはあなたに新しい子のみを与えます。 'Type value observer'を追加すると、すべての子が返されます。 –

答えて

3

新しい投稿が追加されるたびに取得するために他の方法を見てみましょうが、コードは、実行される別のリスナーを添付します。パスの.valueが変更されたため、オリジナルの.observeリスナーによって変更がトリガーされるため、各子に個別に耳を傾ける必要はありません。代わりに、childSnapshotsを繰り返し、必要に応じてデータを追加します。私はあなたのデータとコードでそれをテストしていませんが、あなたはそれを微調整する必要があるかもしれませんが、これはこのように見えます。

let ref = Database.database().reference().child("posts").child(currUser!) 
    ref.observe(.value, with: { (snapshot) in 

     print(snapshot) 
     self.allPosts.removeAll() 
     self.user.descriptions.removeAll() 
     self.user.downloadUrls.removeAll() 

     guard let snapshots = snapshot.children.allObjects as? [DataSnapshot] else { return } 
     for snap in snapshots { 
      self.user.descriptions.append(snap.childSnapshot(forPath: "description").value as! String) 
      self.user.downloadUrls.append(snap.childSnapshot(forPath: "downloadURL").value as! String) 
     } 

     self.tableView.reloadData() 
    }) 
+0

ありがとうございました! –

+0

@JenPersonは持続可能なこのデザインですか? 1,000件の投稿がある場合、クライアント側のデバイスは1,000件すべての投稿を再ダウンロードする必要があります。これは小規模なアプリではうまくいくようですが、大量のデータを持つアプリにとっては良いアイデアではありません。 – DoesData

+0

懸念事項が持続可能性である場合、ページングまたは無限スクロールを伴うデータモデルを作成することができます。これにより、一度にいくつかのエントリにクエリが実行されます。 'childAdded'、' childRemoved'、 'childChanged'を持つデータモデルを使うこともできます。 –

0

問題はここにref.observe(.value, with: { (snapshot) in

です.valueはすべてのデータを返します。したがって、重複したデータが得られます。これを.childAddedに変更すると、新しい投稿情報のみがアプリに返されます。

また、ある時点では、おそらくそのオブザーバーを削除したいと思うでしょう。あなたのアプリの仕組みがわからないので、いつそうなるのか分かりませんが、心に留めておくべきことです。

ref.removeAllObservers()を使用してください。あなたが添付した各リスナーに対して一度説明とdownloadUrlsを追加しますので

データhere

関連する問題