ios - Swift Firebase 长时间延迟加载记录

标签 ios swift firebase firebase-realtime-database offline

我正在使用 Firebase 构建一个 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;
}

在我的联系人 TableView 中

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()
}

我的数据库结构如下

enter image description here

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

最佳答案

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

1) The child added 事件最初为每个 child 触发,然后为之后添加的任何 child 触发。如果您有 1000 个联系人,这意味着在启动时,您将刷新表格 View 1000 次。您最好通过 .value 加载所有联系人并遍历它们,添加到数组,然后在完成后刷新 tableView

2) 与#1 一起,如果您只想按姓氏对它们进行排序,请按 .value 观察节点,遍历快照以填充数组然后排序,然后重新加载 tableView。这将明显更快。

3) childChanged 事件:没有理由按姓氏查询,因为当 child 发生变化时,它只会通知您那个 child ,如果需要,您可以在代码中排序

4) 与观察事件相比,Firebase 查询非常“繁重”。在这种情况下,您实际上并没有特别查询任何内容,因此应该将其删除。只需使用观察事件来加载节点的数据值(value),并在查找该数据的子集时使用查询。

*请注意,这在很大程度上取决于您有多少联系人。对于几千人来说,这些建议很管用。

所以有一个非常酷的设计模式可以让初始数据集的填充变得非常干净。我认为其中一位 Firebaser 将其编写为示例应用程序的一部分。

我们首先定义一个名为 initialLoad 的类级变量并将其设置为 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 英尺的 View :

这里的关键是 .value 事件在 .childAdded 事件之后触发,因此我们利用它在所有子添加事件完成后将 initialLoad 变量设置为 false。

上面的代码是 Swift 2/3,Firebase 2,但它为您提供了如何进行初始加载的概念。

关于ios - Swift Firebase 长时间延迟加载记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41082347/

相关文章:

swift - 更改自定义 UITableViewCell 类中的项目

firebase - 定期将大数据 (json) 导入 Firebase

java - 找不到参数的方法实现()[com.google.firebase :firebase-core:17. 0.0]

iOS:检测用户是否在事件工具包中取消了 "Add to Calendar"?

ios - 向玩家添加观察者时出错

ios - Swift Sprite 工具包垂直背景无限图像

swift - 如何在flutter中访问Firebase实时数据库快照上的子属性?

html - 如何从网站上的链接打开 native iOS 应用程序(日历、笔记...)?

ios - 使用 UIImageView repeatedValue() 初始化 Swift 数组似乎不起作用

ios - 如何获取 UIButton ID?