Swift Firebase用户数据加载时间长

Swift Firebase用户数据加载时间长,swift,firebase,firebase-realtime-database,Swift,Firebase,Firebase Realtime Database,我的应用程序有大约500个用户。在一个屏幕中,我加载学生用户供教师选择。学生名单(400人)的填写时间超过20秒。我想知道是否有更有效的方法来填充数据。要填充的数据是uid、first、last和email 下面是我获取学生用户的函数 var filteredUsers = [User]() var users = [User]() fileprivate func fetchFollowingUserIds() { let ref = Database.database().r

我的应用程序有大约500个用户。在一个屏幕中,我加载学生用户供教师选择。学生名单(400人)的填写时间超过20秒。我想知道是否有更有效的方法来填充数据。要填充的数据是uid、first、last和email

下面是我获取学生用户的函数

  var filteredUsers = [User]()
var users = [User]()

fileprivate func fetchFollowingUserIds() {

    let ref = Database.database().reference().child("session1AllStudents")
    ref.observeSingleEvent(of: .value, with: { (snapshot) in

        guard let userIdsDictionary = snapshot.value as? [String: Any] else { return }
        print(userIdsDictionary)

        userIdsDictionary.forEach({ (key, value) in
            HUD.show(.labeledProgress(title: "Finding Students", subtitle: nil))
            Database.fetchStudentUsersWithUID(uid: key, completion: { (user) in

                self.users.append(user)
                print(self.users)
                self.users.sort(by: { (u1, u2) -> Bool in

                    return u1.lastName.compare(u2.lastName) == .orderedAscending
                })

                self.filteredUsers = self.users
                print(self.filteredUsers.count)
                self.collectionView?.reloadData()
                HUD.hide()
            })

        })


    }) { (err) in
        print("Failed to fetch following userids:", err)
    }

}

extension Database {
static func fetchStudentUsersWithUID(uid: String, completion: @escaping (User) -> ()) {

    Database.database().reference().child("studentUsers").child(uid).observeSingleEvent(of: .value, with: { (snapshot) in

        guard let userDictionary = snapshot.value as? [String: Any] else { return }

        let user = User(uid: uid, dictionary: userDictionary)
        completion(user)

    }) { (err) in
        print("Failed to fetch user for posts:", err)
    }
}
}

数据库“session1AllStudents”是仍然允许选择的所有学生的列表,具有UID:true key:value对

然后我从列表中的UID中的“studentUsers”获取学生信息

--更新--

在看了评论之后,我使用了以下内容

func fetchRemainingStudents() {

    let ref = Database.database().reference()
    ref.child("session1AllStudents").observeSingleEvent(of: .value, with: { (snapshot) in
        HUD.show(.labeledProgress(title: "Finding Students", subtitle: nil))
        for snap in snapshot.children {
            let studentsSnap = snap as! DataSnapshot
            let studentsKey = studentsSnap.key
            let studentDict = snapshot.value as! [String: Any]

            var aStudent = User(uid: studentsKey, dictionary: studentDict)
            let userRef = ref.child("studentUsers").child(studentsKey)
            userRef.observeSingleEvent(of: .value, with: { snapshot in
                let userDict = snapshot.value as! [String:AnyObject]
                let firstName = userDict["firstName"] as! String
                let lastName = userDict["lastName"] as! String
                let email = userDict["email"] as! String

                aStudent.firstName = firstName
                aStudent.lastName = lastName
                aStudent.email = email
                self.users.append(aStudent)

                self.filteredUsers = self.users
                print(self.filteredUsers.count)
                self.users.sort(by: { (u1, u2) -> Bool in

                    return u1.lastName.compare(u2.lastName) == .orderedAscending
                })
                HUD.hide()
                self.collectionView?.reloadData()
            })

        }

    })


}

这有助于加速数据加载。可能会缩短到1-2秒。

您已经更新了代码并获得了更好的性能,但您可以进一步修改它

我制作并测试了下面的代码,从1000个用户中抽取了500个用户。总时间为0.487秒

首先,我们从一个StudentClass和一个数组开始存储它们。例如,该数组可以用作tableView的数据源

class StudentClass {
    var key = ""
    var firstName = ""
    var lastName = ""
    var email = ""

    init(snap: DataSnapshot) {
        let dict = snap.value as! [String: Any]
        self.key = snap.key
        self.firstName = dict["first_name"] as! String
        self.lastName = dict["last_name"] as! String
        self.email = dict["email"] as! String
    }
}

var studentArray = [StudentClass]()
然后,我们将在学生id中读取代码,这将填充一个数组。然后,我们使用该数组从Firebase获取学生,创建学生对象并填充studentArray

func fetchStudents() {

   let studentIdRef = self.ref.child("student_ids")
   let userRef = self.ref.child("users")

   studentIdRef.observeSingleEvent(of: .value, with: { snapshot in
       var keyArray = [String]()
       for child in snapshot.children {
           let snap = child as! DataSnapshot
           keyArray.append(snap.key)
       }
       let lastElement = keyArray.count - 1

       for (index, key) in keyArray.enumerated() {
           let thisUserRef = userRef.child(key)
           thisUserRef.observeSingleEvent(of: .value, with: { userSnap in
               let student = StudentClass(snap: userSnap)
               self.studentArray.append(student)
               if index == lastElement {
                   print("reload tableView")
               }
           })
       }
   })
加快速度的方法之一是在读取所有数据之前不更新UI。我们可以使用后台线程,但在这种情况下,它发生得太快,可能不需要


在获取每个学生对象的for循环中,将执行一个测试,以查看我们是否已完成对所有学生对象的读取,如果已完成,则在加载所有数据后更新ui(例如tableView.reloadData()。

您应该能够在不到一秒钟的时间内加载数千个节点。您的问题中的代码存在许多问题,这些问题可能是问题的一部分。每次循环时,您都在排序、重新分配数组并重新加载tableView。@Jay您能帮我找到一些地方使其更有效吗?不确定您是否审阅了我的答案,但为了更好的性能,我稍微更新了它。