2017-10-09 73 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()),當所有數據已被加載。