Swift Firebase的加载logging延迟很长

我正在使用Firebase构build一个Swift应用程序,而我对这两个人都是新手,所以要温和。 目前,当我打开应用程序,它再次同步整个数据库,并导致2或3秒的滞后用户盯着一个空的tableview。 我怎样才能加快速度呢?

有什么想法吗?

我的代码:

我的loadContacts函数

func loadContact(snap : FIRDataSnapshot) -> Contact { let key = snap.key let contact = (snap.value) as? NSDictionary let c1 = Contact( id: (contact?["id"] as? String)!, firebasekey: key, first_name: (contact?["First Name"] as? String)!, middle_name: (contact?["Middle Name"] as? String)!, last_name: (contact?["Last Name"] as? String)!, suffix: (contact?["Suffix"] as? String)!, company: (contact?["Company"] as? String)!, phone_labe1: (contact?["Phone Label 1"] as? String)!, phone1: (contact?["Phone 1"] as? String)!, phone_label2: (contact?["Phone Label 2"] as? String)!, phone2: (contact?["Phone 2"] as? String)!, email_label1: (contact?["Email Label 1"] as? String)!, email1: (contact?["Email 1"] as? String)!, email_label2: (contact?["Email Label 2"] as? String)!, email2: (contact?["Email 2"] as? String)!, social: (contact?["Social Security Number"] as? String)!, dob: (contact?["Date of Birth"] as? String)!, street: (contact?["Street"] as? String)!, city: (contact?["City"] as? String)!, zip: (contact?["ZIP and Postal Code"] as? String)!, state: (contact?["State and Province"] as? String)!, reg_number: (contact?["Reg Num"] as? String)!, stable_reg_number: (contact?["Stable Reg Num"] as? String)!, emergency_contact: (contact?["Emergency Contact"] as? String)!, emergency_phone: (contact?["Emergency Phone"] as? String)!, drivers_license: (contact?["Driver's License Num"] as? String)!, insurance_carrier: (contact?["Insurance Carrier"] as? String)!, details: (contact?["Details"] as? String)!, insurance_exp: (contact?["Insurance Expiration Date"] as? String)!, insurance_group: (contact?["Insurance Group Num"] as? String)!, insurance_member: (contact?["Insurnace Member Num"] as? String)!, // spelled wrong in database job_title: (contact?["Job Title"] as? String)!, date_modified: (contact?["Modified"] as? String)!, keywords: [], notes: [] ) return c1; } 

并在我的联系表视图

 import UIKit import Firebase class ContactTableViewController: UITableViewController, UISearchBarDelegate, UISearchDisplayDelegate { // MARK: Properties var contactSearchResults : [Contact] = [] // FIRDatabase.database().persistenceEnabled = true let contactRef = FIRDatabase.database().reference().child("contacts") override func viewDidLoad() { contactRef.queryOrdered(byChild: "Last Name").observe(.childAdded) { (snap: FIRDataSnapshot) in contacts.append(loadContact(snap: snap)) self.tableView.reloadData() } contactRef.queryOrdered(byChild: "Last Name").observe(.childChanged) { (snap: FIRDataSnapshot) in // this code here is wrong, but it doesn't matter for demonstration purposes contacts.append(loadContact(snap: snap)) self.tableView.reloadData() } // Uncomment the following line to preserve selection between presentations // self.clearsSelectionOnViewWillAppear = false // Uncomment the following line to display an Edit button in the navigation bar for this view controller. // self.navigationItem.rightBarButtonItem = self.editButtonItem() } 

我的数据库结构像

在这里输入图像说明

联系人(我的问题区域)有大约4000条logging,每个logging有33个独立的子值。

问题中的代码会影响性能。

1)孩子最初为每个孩子添加事件,然后为之后添加的任何孩子添加事件。 如果您有1000个联系人,这意味着启动时,您正在刷新1000次的表视图。 你最好用.value加载所有的联系人,迭代它们,join一个数组,然后在完成时刷新tableView

2)与#1一起,如果你只是想按姓氏sorting,通过.value观察节点,迭代快照来填充数组,然后sorting,然后重新加载tableView。 这将会显着加快。

3)childChanged事件:当孩子变化时,没有理由用姓氏来查询,它会通知你这个孩子,如果需要,你可以在代码中进行sorting

4)与观察事件相比,Firebase查询非常“沉重”。 在这种情况下,你真的不是特别的查询,所以应该被淘汰。 只需使用观察事件来加载节点的数据,并在查找数据的子集时使用查询。

*请注意,这很大程度上取决于你有多less联系人。 几千这些build议工作正常。

所以有一个非常酷的devise模式,使得填充初始数据集真的很干净。 我认为其中一个Firebasers将其作为示例应用程序的一部分进行了编写。

我们首先定义一个名为initialLoad的类variables,并将其设置为true。 然后我们使用一个childAdded观察来加载所有的联系人,并填充我们的tableView数据源数组。

 var initialLoad = true contactsRef.observeEventType(.ChildAdded, withBlock: { snapshot in self.handleChildAdded(withSnap: snapshot) }) 

以及处理childAdded事件的函数,并且最初一次加载每个孩子,并观察之后添加的孩子。

 func handleChildAdded(withSnap: snapshot: FDataSnapshot! ) { let myContact = Contact() myContact.initWithSnap(snapshot) myDataSourceArray.append(myContact) //upon first load, don't reload the tableView until all children are loaded if ( self.initialLoad == false ) { self.contactsTableView.reloadData() } } 

现在棘手的一点

 //this .Value event will fire AFTER the child added events to reload the tableView // the first time and to set subsequent childAdded events to load after each child is // added in the future contactsRef.observeSingleEventOfType(.Value, withBlock: { snapshot in print("inital data loaded so reload tableView!") self.itemsTableView.reloadData() self.initialLoad = false }) 

10K英尺的观点:

这里的关键是.value事件触发.childAdded事件之后,所以我们正在利用它来设置initialLoadvariables为false后,所有的子添加事件完成。

上面的代码是Swift 2/3,Firebase 2,但它给你如何做你的初始负载的概念。