2017-10-09 71 views
0

我的应用程序有大约500个用户。在一个屏幕中,我加载了供教师选择的学生用户。学生名单(400)需要20秒才能填充。我想知道是否有更有效的方式来填充数据。要填充的数据是uid,第一个,最后一个,电子邮件。Swift Firebase用户数据的长时间加载时间

这是我的功能来获取学生用户。

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:真正的关键字:值对。

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

--UPDATED--

我在看完评论后使用了以下内容。

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秒。

+0

您应该可以在不到一秒钟内加载数千个节点。代码中存在许多问题,可能是问题的一部分。您正在排序,重新分配数组并重新加载tableView,每次通过循环。 – Jay

+0

@Jay你能帮我解决一些可以提高效率的地方吗? –

+0

不知道你是否回顾了我的回答,但为了更好的表现,我稍微更新了它。 – Jay

回答

1

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

我制作并测试了下面的代码,将500个用户从列表1000中抽出。总时间为.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将填充数组。然后,我们使用该阵列从火力地堡让学生,创建学生对象,并填充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") 
       } 
      }) 
     } 
    }) 

一个加快速度,直到你在读的所有数据不更新用户界面的方式。我们可以使用后台线程,但在这种情况下,它发生得非常快,可能不需要。

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