尝试使用.reversed()对Firebase提取进行排序时崩溃

时间:2017-03-21 13:00:03

标签: ios firebase firebase-realtime-database uicollectionview

我尝试从我的数据库中进行提取以填充集合视图,按照最新的顺序填充到最旧的。我尝试使用snap.children.allObjects.reversed(),但我的应用在加载时崩溃了。这是完整的获取功能:

func fetchPosts() {

    let ref = FIRDatabase.database().reference()
    ref.child("users").queryOrderedByKey().observe(.value, with: { snapshot in

        let users = snapshot.value as! [String : AnyObject]

        for (_, value) in users {

            if let uid = value["uid"] as? String {

                if uid == FIRAuth.auth()?.currentUser?.uid {

                    if let followingUsers = value["following"] as? [String : String] {

                        for (_, user) in followingUsers {
                            self.following.append(user)
                        }
                    }
                    self.following.append(FIRAuth.auth()!.currentUser!.uid)

                    ref.child("posts").queryOrderedByKey().observeSingleEvent(of: .value, with: { (snap) in

                        for postSnapshot in snap.children.allObjects.reversed() as! [FIRDataSnapshot] {
                            let value = postSnapshot.value as! [String : AnyObject]

                            if let userID = value["userID"] as? String {
                                for each in self.following {
                                    if each == userID {

                                        let posst = Post()
                                        if let poster = value["poster"] as? String, let likes = value["likes"] as? Int, let pathToImage = value["pathToImage"] as? String, let postID = value["postID"] as? String {

                                            posst.poster = poster
                                            posst.likes = likes
                                            posst.pathToImage = pathToImage
                                            posst.postID = postID
                                            posst.userID = userID
                                            if let people = value["peopleWhoLike"] as? [String : AnyObject] {
                                                for (_, person) in people {
                                                    posst.peopleWhoLike.append(person as! String)
                                                }
                                            }
                                            posts.append(posst)
                                        }
                                    }
                                }
                                self.collectionView.reloadData()
                            }
                        }
                    })
                    ref.removeAllObservers()
                }
            }
        }
    })
}

错误为EXC_BAD_INSTRUCTION (code=EXC_1386_INVOP, subcode=0x0),警告来自' ReversedRandomAccessCollection< [Any]>' (又名' ReversedRandomAccessCollection>')到不相关的类型' [FIRDataSnapshot]'总是失败。

.reversed不是解决这个问题的方法吗?实际上,我的代码没有.reversed按顺序加载帖子,从最顶层到底部最新。我该如何切换它?

编辑:帖子的Firebase片段:

"posts" : {
"-KfWzWv8rP38bUreDupj" : {
  "likes" : 1,
  "pathToImage" : "https://firebasestorage.googleapis.com/v0/b/cloudcamerattt.appspot.com/o/posts%2F1JSgke8QqFds4CxF2Z4MhuzbRoW2%2F-KfWzWv8rP38bUreDupj.jpg?alt=media&token=fef86bea-1ae2-4e1e-82fa-6209bc281a5e",
  "peopleWhoLike" : {
    "-KfX29jTcwaQDpkdIVX8" : "yI6NokUl2mTa7Uah4SgtAiulTJH2",
    "-KfXQJBRemZUCI2ieT94" : "MpnGvQj7ZOdz12zKD0bTeX1kp0B3"
  },
  "postID" : "-KfWzWv8rP38bUreDupj",
  "poster" : "Harry Potter",
  "userID" : "1JSgke8QqFds4CxF2Z4MhuzbRoW2"
},

编辑2:添加时间戳

var timestamp: Int!添加到我的Post对象,然后将其添加到我的上传功能中:

func uploadToFirebase() {
    AppDelegate.instance().showActivityIndicator()

    let uid = FIRAuth.auth()!.currentUser!.uid
    let ref = FIRDatabase.database().reference()
    let storage = FIRStorage.storage().reference(forURL: "gs://cloudcamerattt.appspot.com")
    let key = ref.child("posts").childByAutoId().key
    let imageRef = storage.child("posts").child(uid).child("\(key).jpg")
    let data = UIImageJPEGRepresentation(self.previewImage.image!, 0.6)
    var Timestamp: TimeInterval {
        return NSDate().timeIntervalSince1970 * 1000
    }

    let uploadTask = imageRef.put(data!, metadata: nil) { (metadata, error) in
        if error != nil {
            print(error!.localizedDescription)
            AppDelegate.instance().dismissActivityIndicator()
            return
        }

        imageRef.downloadURL(completion: { (url, error) in

            if let url = url {
                let feed = ["userID" : uid,
                            "pathToImage" : url.absoluteString,
                            "likes" : 0,
                            "poster" : FIRAuth.auth()!.currentUser!.displayName!,
                            "postID" : key,
                            "timestamp" : (0-Timestamp)] as [String : Any]

                let postFeed = ["\(key)" : feed]
                ref.child("posts").updateChildValues(postFeed)
                AppDelegate.instance().dismissActivityIndicator()

                let feedController = self.storyboard?.instantiateViewController(withIdentifier: "feedVC") as! FeedViewController
                feedController.navigationItem.setHidesBackButton(true, animated: false)

                self.tabBarController?.selectedIndex = 0
            }
        })
    }
    uploadTask.resume()
}

然后将其添加到我的fetch中:

                                        let posst = Post()
                                        if let poster = value["poster"] as? String, let likes = value["likes"] as? Int, let pathToImage = value["pathToImage"] as? String, let postID = value["postID"] as? String, let timestamp = value["timestamp"] as? Int {

                                            posst.poster = poster
                                            posst.likes = likes
                                            posst.pathToImage = pathToImage
                                            posst.postID = postID
                                            posst.userID = userID
                                            posst.timestamp = timestamp

更新了抓取功能(导致崩溃Could not cast value of type 'FIRDataSnapshot' (0x10584eee8) to 'NSArray' (0x107b43dd8).):

func fetchPosts() {

    let ref = FIRDatabase.database().reference()
    ref.child("users").queryOrderedByKey().observe(.value, with: { snapshot in

        let users = snapshot.value as! [String : AnyObject]

        for (_, value) in users {

            if let uid = value["uid"] as? String {

                if uid == FIRAuth.auth()?.currentUser?.uid {

                    if let followingUsers = value["following"] as? [String : String] {

                        for (_, user) in followingUsers {
                            self.following.append(user)
                        }
                    }
                    self.following.append(FIRAuth.auth()!.currentUser!.uid)

                    for child in snapshot.children.reversed() {
                        let snap = child as! [FIRDataSnapshot]

                    ref.child("posts").queryOrdered(byChild: "timestamp").observeSingleEvent(of: .value, with: { (snap) in

                            if let userID = value["userID"] as? String {
                                for each in self.following {
                                    if each == userID {

                                        let posst = Post()
                                        if let poster = value["poster"] as? String, let likes = value["likes"] as? Int, let pathToImage = value["pathToImage"] as? String, let postID = value["postID"] as? String, let timestamp = value["timestamp"] as? Int {

                                            posst.poster = poster
                                            posst.likes = likes
                                            posst.pathToImage = pathToImage
                                            posst.postID = postID
                                            posst.userID = userID
                                            posst.timestamp = timestamp
                                            if let people = value["peopleWhoLike"] as? [String : AnyObject] {
                                                for (_, person) in people {
                                                    posst.peopleWhoLike.append(person as! String)
                                                }
                                            }
                                            posts.append(posst)
                                        }
                                    }
                                }
                                self.collectionView.reloadData()
                            }
                        })
                    }
                    ref.removeAllObservers()
                }
            }
        }
    })
}

2 个答案:

答案 0 :(得分:1)

尝试

for child in snapshot.children.reversed() {
     let snap = child as! FIRDataSnapshot
     print(snap)
}

您按键排序,将最旧的加载到最新。如果您想要撤销订单,让Firebase执行繁重的工作,请使用此处发布的反向时间顺序技术

In Firebase, how can I query the most recent 10 child nodes?

然后很容易进行反向查询...

"posts" : {
   "-KfWzWv8rP38bUreDupj" : {
      "likes" : 1,
      "pathToImage" : "https:/...",
      "peopleWhoLike" : {
        "-KfX29jTcwaQDpkdIVX8" : "yI6NokUl2mTa7Uah4SgtAiulTJH2",
        "-KfXQJBRemZUCI2ieT94" : "MpnGvQj7ZOdz12zKD0bTeX1kp0B3"
      },
      "postID" : "-KfWzWv8rP38bUreDupj",
      "poster" : "Harry Potter",
      "timestamp" : -1.46081635550362E12,   //Just add this child
      "userID" : "1JSgke8QqFds4CxF2Z4MhuzbRoW2"
},

然后

ref.child("posts").queryOrdered(byChild: "timestamp").observe(...

此外,作为孩子可能不需要重复的postID,因为它也是帖子的关键。

答案 1 :(得分:0)

你是正确的,你需要在某处投射某些东西,因为Swift只知道我们从Any数组开始。问题是你在错误的地方投错了。在for循环内部的开头转换postSnapshot

弄清楚这种事情的方法是制作一个简化的游乐场示例。你正在做相同的事情:

let arr : [Any] = [1,2,3]
for i in arr.reversed() as! [Int] { // crash
}

然而,我们在该示例中所知道的并不是arr.reversed();是i是一个Int。这很好:

let arr : [Any] = [1,2,3]
for i in arr.reversed() {
    if let i = i as? Int {
        // now it is safe to use `i`
    }
}

你的情况是平行的。在for循环开始时,您需要将postSnapshot强制转换为FIRDataSnapshot。现在你可以继续了。