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

Ios 尝试使用.reversed()对Firebase提取进行排序时崩溃,ios,firebase,firebase-realtime-database,uicollectionview,Ios,Firebase,Firebase Realtime Database,Uicollectionview,我试图从我的数据库中提取数据,以填充集合视图,顺序是从最新到最旧。我尝试使用snap.children.allObjects.reversed(),但我的应用程序在加载时崩溃。下面是完整的fetch函数: func fetchPosts() { let ref = FIRDatabase.database().reference() ref.child("users").queryOrderedByKey().observe(.value, with: { snapshot i

我试图从我的数据库中提取数据,以填充集合视图,顺序是从最新到最旧。我尝试使用
snap.children.allObjects.reversed()
,但我的应用程序在加载时崩溃。下面是完整的fetch函数:

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()
                }
            }
        }
    })
}
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()
}
错误为
EXC_BAD_指令(code=EXC_1386_INVOP,子代码=0x0)
,警告从“ReversedRandomAccessCollection”(又名“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时间戳:Int添加到我的
Post
对象,然后将其添加到我的上载功能中:

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()
                }
            }
        }
    })
}
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()
}
然后将其添加到我的获取中:

                                        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
更新的获取函数(导致崩溃
无法将“FIRDataSnapshot”(0x10584eee8)类型的值强制转换为“NSArray”(0x107b43dd8)。

试一试

您正在按键订购,该键将从最旧的加载到最新的。如果您想颠倒顺序,让Firebase来完成繁重的工作,请使用此处发布的颠倒时间顺序的技术

然后很容易进行反向查询

"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,因为它也是帖子的关键。

你说得对,你需要在某个地方施放一些东西,因为斯威夫特只知道我们从一个数组开始。问题是你在错误的地方投错了东西。在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。现在您可以继续了。

通常,在您的问题中发布Firebase结构的片段是一个好主意;作为文本,请不要图片。您可以通过Firebase控制台中的export(右上三点)函数以文本形式获取JSON结构。@Jay抱歉,我现在添加了一个片段-我猜是“posts”(这是fetch用来填充提要的内容)?谢谢,我正在阅读您的另一个答案,并试图添加一个时间戳。我编辑了我的帖子以显示我正在尝试的内容,但我的收藏视图没有加载,我想是因为那里的帖子已经没有时间戳了?@KingTim Correct。如果希望让Firebase进行排序,则需要在所有帖子中包含timestamp子节点。你可以在代码中完成,但让Firebase在服务器级别进行排序并以正确的顺序向你提供数据要快得多。好吧,很酷,所以我的思路是正确的-但我不理解你的评论,我是否应该以现在的方式添加时间戳呢?是否有其他方法让Firebase进行排序?@KingTim根据我上面的评论,所有子节点都需要时间戳子节点。你这样做几乎是正确的,除了你把时间戳写成一个正值——这意味着旧的帖子将“在底部”。您想要相反的结果,因此时间戳需要写为负值;setValue(0-t1)//注意负值。重新阅读链接的帖子,并对其进行解释。如果我在字典中上载时间戳和所有其他值时,使用
“timestamp”:(0-timestamp)
,而不是使用nodeRef,这会是同一件事吗?我把我的上传功能放在我的编辑中。