2016-12-11 7 views
0

私はFirebaseを使用してSwiftアプリケーションを構築しています。現在、アプリケーションを開くと、データベース全体が再び同期され、ユーザーが空のテーブルビューを見つけた場合、2〜3秒の遅延が発生します。どうすればこれをスピードアップできますか?Swift Firebaseが長い遅延でレコードをロードしています

どのような考えですか?

マイコード:

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

のような構造をしている
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; 
} 

そして、私の連絡先テーブルビューで

マイloadContacts機能

連絡先(私の問題領域)には、約4000のレコードがあり、33個の子供がそれぞれ値を持っています。

+0

Firebaseは、データをローカルに保存する必要がなくなるリアルタイムデータベースです。これは、使用するケースによって異なります。つまり、FirebaseからtableViewをロードするのに2〜3秒の遅延がある場合は、ほとんど直ちに感じられるはずの他の問題があります。数千分の1秒間で数千人のユーザーが読み込まれます。他の懸念事項は、あなたがユーザーに表示している(たとえば)tableViewに適用可能なFirebaseからのデータだけを取得する必要があるため、「データベース全体をもう一度同期する」ということです。 – Jay

+0

@Jayご返信ありがとうございます!私はほぼ即時の積載時間で完璧にうまくいっていますが、遅れを引き起こす原因について何か提案がありますか? –

+0

@NickWinnerこの質問に答えるために、コードとデータベースの構造をもっと見る必要があります。 –

答えて

6

質問にはパフォーマンスに影響を与えるコードがいくつかあります。

1)子は最初にすべての子に対してイベント火災を追加し、その後に追加された子に対してイベント火災を追加しました。連絡先が1000人ある場合は、起動時にテーブルビューを1000回更新することを意味します。 .valueですべての連絡先をロードし、それらを反復し、配列に追加して、完了したらtableViewを更新する方がよいでしょう。

2)#1と一緒に、 .valueでノードを観察し、スナップショットを反復処理して配列にデータを格納し、次にsortをソートしてから、再度読み込みます。それははるかに速くなります。

3)childChangedイベント:とき、子の変化、それだけでその子を通知し、

4必要に応じて再び、あなたはコードでソートできるよう最後の名前で照会する理由はありません)Firebaseクエリがされていますイベントを観察するためには非常に「重い」。この場合、実際には何も検索していないので、削除する必要があります。ノードの価値のあるデータをロードし、そのデータのサブセットを探しているときにクエリを使用するには、observeイベントを使用します。

*この件数は、お持ちの連絡先の数によって異なります。数千人の人々にとって、これらの提案はうまく機能します。

本当にクールなデザインパターンがあり、最初のデータセットを実際にきれいにすることができます。 Firebasersの一人が、それをサンプルアプリケーションの一部として書いたと思います。

まず、initialLoadという名前のクラスレベルの変数を定義し、それをtrueに設定します。次に、childAdded observeを使用してすべての連絡先をロードし、tableView dataSource配列に値を設定します。

var initialLoad = true 

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

とchildAddedイベントを処理する関数であり、最初は各子を1つずつ読み込み、その後に追加された子を監視します。

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イベントが発生AFTER .childAddedのイベントは、私たちがinitialLoadを設定することを活用しているということです変数をfalseにするすべての子追加イベントが完了した後。

上記のコードはSwift 2/3、Firebase 2ですが、初期ロードの仕方の概念を示しています。

+0

最後の例をありがとう! –

+0

ありがとうございます!これは私に約7秒の遅れから約3までの時間を要しました。 –