4

新しい Firebaseからの拡張機能の質問は 、データを取得して tableView に配置します (Swift)

Firebase コードを viewDidLoad に移動することで、Post のすべてのテキスト部分を現在表示できるようになります。しかし、まだ画像をtableViewに入れることはできません。画像の取得を確認しましたが、成功しました。Firebase から取得した画像がポスト配列に含まれていなかったと思います。

これは私の修正コードです:

  import UIKit
  import Firebase
  import FirebaseStorage

class timelineTableViewController: UITableViewController {
var posts = [Post]()
var databaseRef: FIRDatabaseReference!
var storageRef: FIRStorageReference!

override func viewDidLoad() {
    super.viewDidLoad()
    databaseRef = FIRDatabase.database().reference()
    storageRef = FIRStorage.storage().reference()
    let userPostRef = self.databaseRef.child("posts")
    userPostRef.queryOrderedByChild("time").observeEventType(.ChildAdded, withBlock: {(snapshot) in
        if let postAdd  = snapshot.value as? NSDictionary{

            let url = snapshot.value?["postPhoto"] as! String
            let userPhotoUrl = snapshot.value?["userPhoto"] as! String
            let myPost = Post(data: postAdd)

            FIRStorage.storage().referenceForURL(url).dataWithMaxSize(10 * 1024 * 1024, completion: { (data, error) in
                let postPhoto = UIImage(data: data!)

                                    })
            FIRStorage.storage().referenceForURL(userPhotoUrl).dataWithMaxSize(10 * 1024 * 1024, completion: { (data, error) in
                let userPhoto = UIImage(data: data!)
                                })

            self.posts.insert(myPost, atIndex: 0)
            self.tableView.reloadData()

        }




})

}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    // #warning Incomplete implementation, return the number of sections
    return 1
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return posts.count


}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cellIdentifier = "postCell"
    let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath)as! timelineTableViewCell
    //Dispatch the main thread here
    dispatch_async(dispatch_get_main_queue()) {
        cell.usernameLabel.text = self.posts[indexPath.row].username
        cell.postText.text = self.posts[indexPath.row].postText
        cell.timeLabel.text = self.posts[indexPath.row].time
        cell.postPhoto.image = self.posts[indexPath.row].postPhoto
        cell.userPhoto.image = self.posts[indexPath.row].userPhoto


    }
    return cell
   }
   }

そして、Post の私の構造体は、それが役立つことを願っています!

struct  Post {
var username: String?
var postText: String?
var time: String?
var userPhoto: UIImage?
var postPhoto: UIImage?
var url: String?
var userPhotoUrl:String?
init(data: NSDictionary) {
   username = data["username"] as? String
   postText = data["postText"] as? String
    time = data["time"]as? String
    userPhoto = data["userPhoto"] as? UIImage
    postPhoto = data["postPhoto"] as? UIImage
    url = data["postPhoto"] as? String
    userPhotoUrl = data["userPhoto"] as? String
}

}

アドバイスをいただけると幸いです!

4

3 に答える 3

2

ここでの問題は、写真が非同期でダウンロードされているため、投稿が写真情報を取得できないことのようです。

疑似コードを使用して、あなたがしていることは次のとおりです。

Get information from database
  Create post object
    Begin downloading post photo
      Populate post object with post photo
    Begin downloading user photo
      Populate post object with user photo
  Return post object

何が起こっているかというと、写真がダウンロードされる前に投稿オブジェクトが返されています (dataWithMaxSize:completion:呼び出しが非同期であるため)。最終的に行う必要があるのは、次のようなものです。

Get information from database
  Create post object
    Begin downloading post photo, etc.
      Begin downloading user photo, etc.
        Return post object, now that it's fully populated

これは一般に「コールバック地獄」として知られるパラダイムです。非同期コードをかなり深くネストし、読み取りとデバッグが難しくなるためです。JavaScript はこれに対処するために Promises を発明しましたが、残念ながら Swift はそのようなものに対する第一級のサポートを持っていません (guardしかし、その方向への良い動きです)。より同期的に見える非同期フレームワークを使用するBoltsのようなライブラリがありますが、コードはもう少し複雑になります。

できること (セマフォ/ミューテックスを追加し、オブジェクトを作成する前にダウンロードが完了するのを待つ) がありますが、それらはかなり高度な概念であり、それらを試す前に同期/非同期プログラミングをマスターしたいと思います。

于 2016-06-20T18:20:50.347 に答える
1

次の 2 行を削除します。

userPhoto = data["userPhoto"] as? UIImage
postPhoto = data["postPhoto"] as? UIImage

このコードを更新します。

FIRStorage.storage().referenceForURL(url).dataWithMaxSize(10 * 1024 * 1024, completion: { (data, error) in
     dispatch_async(dispatch_get_main_queue()) {
            myPost.postPhoto = UIImage(data: data!)
            self.tableView.reloadData()
     }

                                })
FIRStorage.storage().referenceForURL(userPhotoUrl).dataWithMaxSize(10 * 1024 * 1024, completion: { (data, error) in
     dispatch_async(dispatch_get_main_queue()) {
            myPost.userPhoto = UIImage(data: data!)
            self.tableView.reloadData()
            }
     })
于 2016-07-05T14:35:23.313 に答える