Noțiuni de bază cu Firestore Cloud pentru iOS

Coderii mobili au profitat de multitudinea de ani de la baza de date Firebase RealPlayer a platformei Mobile Backend ca serviciu (MBaaS), ajutându-i să se concentreze pe construirea de funcții pentru aplicațiile lor, fără a fi nevoiți să vă faceți griji în ceea ce privește infrastructura și baza de date back-end. Prin facilitarea stocării și persistenței datelor în nor și asigurarea autentificării și a securității, Firebase permite coderilor să se concentreze pe partea clientului. 

Anul trecut, Google a anunțat încă o soluție de bază de date back-end, Cloud Firestore, construită de la bază cu promisiunea unei scalabilități și intuiții mai mari. Cu toate acestea, acest lucru a introdus o anumită confuzie în ceea ce privește locul său în legătură cu produsul Google, deja existent, baza de date Firebase Realtime. Acest tutorial va evidenția diferențele dintre cele două platforme și avantajele distincte ale fiecărei platforme. Veți învăța cum să lucrați cu referințe la documentele Firestore, precum și să citiți, scrieți, actualizați și ștergeți date în timp real, construind o aplicație simplă de mementouri.

Obiectivele acestui tutorial

Acest tutorial vă va expune la Cloud Firestore. Veți învăța cum să utilizați platforma pentru persistența și sincronizarea bazei de date în timp real. Vom aborda următoarele subiecte:

  • ceea ce este Cloud Firestore
  • modelul de date Firestore
  • înființarea unui nou magazin Cloud Firestore
  • crearea și colaborarea cu referințele din Cloud Firestore
  • citirea datelor în timp real de la Cloud Firestore
  • crearea, actualizarea și ștergerea datelor
  • filtrarea și interogările compuse

Cunoașterea presupusă

Acest tutorial presupune că ați avut o anumită expunere la Firebase și un fundal în curs de dezvoltare cu Swift și Xcode.

Ce este Firestore-ul din Cloud?

Ca Firebase Realtime Database, Firestore furnizează dezvoltatorilor de dispozitive mobile și web, cu o soluție cloud computing platformă, care să persiste în timp real, indiferent de latența rețelei sau de conexiunile la internet, precum și integrarea fără probleme a suitei de produse Google Cloud Platform. Pe lângă aceste asemănări, există avantaje și dezavantaje distincte care se diferențiază una de cealaltă. 

Model de date

La un nivel fundamental, baza de date Realtime stochează datele ca un arbore JSON mare, monolitic, ierarhic, în timp ce Firestore organizează date în documente și colecții, precum și sub-colecții. Aceasta necesită mai puțin denormalizare. Stocarea datelor într-un arbore JSON are avantajele simplității atunci când vine vorba de a lucra cu cerințe simple de date; cu toate acestea, devine mai greoaie la scară atunci când lucrează cu date ierarhice mai complexe. 

Suport Offline

Ambele produse oferă suport offline, stocarea activă a cache-urilor în cozi atunci când nu există o conexiune latentă sau nici o conectivitate la rețea - sincronizarea schimbărilor locale în spate, atunci când este posibil. Firestore acceptă sincronizarea offline pentru aplicațiile web în plus față de aplicațiile mobile, în timp ce baza de date Realtime permite numai sincronizarea mobilă.

Interogări și tranzacții 

Baza de date în timp real suportă doar capacități limitate de sortare și filtrare - puteți sorta sau filtra numai pe un nivel de proprietate, dar nu și pe ambele, într-o singură interogare. Interogările sunt, de asemenea, adânci, ceea ce înseamnă că întoarce un mare sub-arbore al rezultatelor. Produsul acceptă operații simple de scriere și de tranzacționare care necesită o inversare completă. 

Firestore, pe de altă parte, introduce interogări de indexare cu sortare și filtrare complexă, permițându-vă să combinați acțiunile pentru a crea filtre de lanț și sortare. De asemenea, puteți executa interogări superficiale care returnează sub-colecții în locul întregii colecții pe care ați obține-o cu baza de date Realtime. Tranzacțiile sunt de natură atomică, indiferent dacă trimiteți o operație batch sau o singură operațiune, operațiunile repetând automat până când se încheie. În plus, baza de date în timp real suportă tranzacții individuale de scriere, în timp ce Firestore oferă operațiuni de grup în mod atomic.

Performanță și scalabilitate

Baza de date în timp real, așa cum vă așteptați, este destul de robustă și are o latență redusă. Cu toate acestea, bazele de date sunt limitate la anumite regiuni, în funcție de disponibilitatea zonelor. Firestore, pe de altă parte, găzduiește date orizontale în mai multe zone și regiuni pentru a asigura disponibilitatea globală reală, scalabilitatea și fiabilitatea. De fapt, Google a promis că Firestore va fi mai fiabil decât baza de date Realtime. 

Un alt neajuns al bazei de date Realtime este limitarea la 100.000 de utilizatori simultani (100.000 de conexiuni concurente și 1.000 de înregistrări / secundă într-o singură bază de date), după care va trebui să vă stricați baza de date (împărțiți baza de date în mai multe baze de date) . Firestore scară automat în mai multe situații, fără a fi nevoie să interveniți. 

Proiectat de la bază cu înalță în minte, Firestore are o nouă arhitectură schematică care replică datele în mai multe regiuni, are grijă de autentificare și gestionează alte probleme legate de securitate în cadrul SDK-ului său de pe partea clientului. Noul model de date este mai intuitiv decât Firebase, asemănător cu alte soluții similare de baze de date NoSQL precum MongoDB, oferind în același timp un motor mai puternic de interogare. 

Securitate 

În cele din urmă, baza de date Realtime, după cum știți din tutorialele anterioare, gestionează securitatea prin reguli de cascadă cu declanșatoare separate de validare. Aceasta funcționează cu Regulile bazei de date Firebase, validând datele dvs. separat. Firestore, pe de altă parte, oferă un model de securitate mai simplu și mai puternic, profitând de regulile de securitate Cloud Firestore și de Managementul identității și accesului (IAM), cu excepția automată a validării datelor.

Modelul de date Firestore

Firestore este o bază de date bazată pe documente NoSQL, constând în colecții de documente, fiecare conținând date. Deoarece este o bază de date NoSQL, nu veți obține tabele, rânduri și alte elemente pe care le veți găsi într-o bază de date relațională, ci seturi de perechi cheie / valoare pe care le-ați găsi în documente. 

Creați documente și colecții implicit prin atribuirea de date unui document și dacă documentul sau colecția nu există, acesta va fi creat automat pentru dvs., deoarece colecția trebuie să fie întotdeauna nodul rădăcină (primul). Aici este o schemă simplă a sarcinilor din proiectul pe care veți lucra în curând, constând din colecția Tasks, precum și numeroase documente care conțin două câmpuri, numele (șirul) și un steag pentru a determina dacă sarcina este executată (boolean).

Să descompunem fiecare dintre ele astfel încât să le înțelegem mai bine. 

Colecții

Sinonime cu tabelele de baze de date din lumea SQL, colecțiile conțin unul sau mai multe documente. Colecțiile trebuie să fie elementele rădăcinilor din schema dvs. și pot conține numai documente, nu alte colecții. Cu toate acestea, vă puteți referi la un document care, la rândul său, se referă la colecții (sub-colecții).

În diagrama de mai sus, o sarcină constă din două câmpuri primitive (nume și realizate), precum și o sub-colecție (sub-sarcină) care constă din două domenii primitive proprii. 

Documente

Documentele constau din perechi de chei / valoare, valorile având unul dintre următoarele tipuri: 

  • câmpuri primitive (cum ar fi șiruri de caractere, numere, boolean)
  • obiecte imbricate complexe (liste sau matrice de primitive)
  • sub-colecții

Obiectele imbricate sunt, de asemenea, numite hărți și pot fi reprezentate în document, după cum urmează. Următorul exemplu este un exemplu de obiect imbricat și de matrice, respectiv:

ID: 2422892 // nume primitiv: "Amintiți-vă să cumpărați lapte" detaliu: // note imbricate de obiecte: "Aceasta este o sarcină pentru a cumpăra lapte de la magazin" create: 2017-04-09 datorită: 2017-04-10 făcut: notificare falsă: ["2F22-89R2", "L092-G623", "H00V-T4S1"] ... 

Pentru mai multe informații despre tipurile de date acceptate, consultați documentația Google Data Types. Apoi, veți crea un proiect pentru a lucra cu Cloud Firestore.

Configurarea proiectului

Dacă ați lucrat anterior cu Firebase, multe dintre acestea ar trebui să vă fie cunoscute. În caz contrar, va trebui să creați un cont în Firebase și să urmați instrucțiunile din secțiunea "Configurarea proiectului" din tutorialul nostru anterior, începeți cu autentificarea Firebase pentru iOS . 

Pentru a urmări împreună cu acest tutorial, clonați repo proiectul tutorial. Apoi, includeți biblioteca Firestore de cătreadăugând următoarele la dvs. Podfile:

pod "Firebase / Core" pod "Firebase / Firestore"

Introduceți următoarele în terminal pentru a vă construi biblioteca:

pod instalare

Apoi treceți la Xcode și deschideți .xcworkspace fişier. Navigați la AppDelegate.swift fișier și introduceți următoarele în cadrul aplicare: didFinishLaunchingWithOptions: metodă:

FirebaseApp.configure ()

În browserul dvs., accesați consola Firebase și selectați Bază de date în partea stângă. 

Asigurați-vă că selectați opțiunea pentru Începeți în modul Test astfel încât să nu aveți probleme de securitate în timp ce experimentăm și să luați în considerare nota de securitate atunci când mutați aplicația în producție. Acum sunteți gata să creați o colecție și unele documente de probă.

Adăugarea unei colecții și a unui exemplu de document

Pentru a începe, creați o colecție inițială, Sarcini, selectând Adăugați o colecție butonul și denumirea colecției, după cum se arată mai jos:

Pentru primul document, veți lăsa Documentul necompletat, care va genera automat un ID pentru dvs. Documentul va consta doar din două domenii: Nume și Terminat.

Salvați documentul și ar trebui să puteți confirma colecția și documentul împreună cu ID-ul generat automat:

Cu baza de date configurată cu un exemplu de document în cloud, sunteți gata să începeți să implementați Firestore SDK în Xcode.

Crearea și lucrul cu referințele bazei de date

Deschideți MasterViewController.swift fișier în Xcode și adăugați următoarele linii pentru a importa biblioteca:

importați clasa Firebase MasterViewController: UITableViewController @IBOutlet slab var addButton: UIBarButtonItem! privat documente var: [DocumentSnapshot] = [] publice sarcini var: [Task] = [] privat ascultător var: ListenerRegistration! ... 

Aici, pur și simplu, creați o variabilă de ascultător care vă va permite să declanșați o conexiune la baza de date în timp real atunci când există o schimbare. De asemenea, creați un DocumentSnapshot referință care va conține imaginea temporară a datelor.

Înainte de a continua cu controlerul de vizualizare, creați un alt fișier rapid, Task.swift, care va reprezenta modelul dvs. de date:

import Structură Task var nume: String var făcut: Bool var id: String var dicționar: [String: Oricare] retur ["nume" [String: Oricare], id: String) păstrați numele = dicționar ["nume"] ca? String, să terminăm = dictionary ["done"] ca? Bool else returnați nil self.init (nume: nume, făcut: făcut, id: id)

Fragmentul de cod de mai sus include o proprietate comodă (dicționar) și o metodă (init) care va ușura populația obiectului modelului. Reveniți la controlerul de vizualizare și declarați o variabilă globală de setter care va constrânge interogarea de bază la cele 50 de înregistrări de top din lista de sarcini. De asemenea, veți elimina ascultătorul odată ce ați setat variabila de interogare, așa cum este indicată în didSet proprietate de mai jos:

fileprivate func baseQuery () -> Query returnați Firestore.firestore () colecție ("Tasks") limit (la: 50) queryprivate var interogare: Query? ifSet ifScharest = ascultător listener.remove () override func vizualizareDidLoad () super.viewDidLoad () self.query = baseQuery () override func vizualizareWillDisappear (_ animated: Bool) super.viewWillDisappear animat) self.listener.remove ()

Citirea datelor în timp real din Firestore de la Cloud

Cu referința documentului în loc, în viewWillAppear (_animat: Bool), asociați ascultătorul pe care l-ați creat mai devreme cu rezultatele interogării de interogare și pentru a prelua o listă de documente. Aceasta se face prin apelarea metodei Firestore interogare? .addSnapshotListener:

auto.listener = interogare? .addSnapshotListener (documente, eroare) în gardă let snapshot = documente altceva print ("Eroare la preluarea rezultatelor documentelor: \ (error!)") return let results = snapshot.documents.map  ) -> Sarcina în if let task = Task (dicționar: document.data (), id: document.documentID) return task else fatalError ("Nu se poate inițializa tipul \ (Task.self) () self.tasks = rezultate self.doctable = snapshot.documents self.tableView.reloadData ()

Închiderea de mai sus atribuie snapshot.documents prin maparea matricei în mod iterativ și prin înfășurarea acestuia într-un nou model Sarcină obiect model exemplu pentru fiecare element de date din instantaneu. Deci, cu doar câteva rânduri, ați citit cu succes în toate sarcinile din nor și le-ați atribuit la nivel mondial sarcinimulțime. 

Pentru a afișa rezultatele, introduceți următoareleTableViewmetode delegate:

suprascrie func numOffSections (in tableView: UITableView) -> Int return 1 suprascrie func tableView (_ tableView: UITableView, numberOfRowsInSection sectiune: Int) -> int return tasks.count override func tableView (_tableView: UITableView, cellForRowAt indexPath : IndexPath) -> UITableViewCell lasa celula = tableView.dequeueReusableCell (cuIdentifier: "Cell", pentru: indexPath) permite item = tasks [indexPath.row] cell.textLabel! .Text = item.name cell.textLabel! .TextColor = item.done == false? UICcolor negru: UICcolor.lightGray retur cell

În acest stadiu, construiți și conduceți proiectul, iar în Simulator ar trebui să puteți observa datele care apar în timp real. Adăugați date prin consola Firebase și ar trebui să vedeți că aceasta apare instantaneu în simulatorul de aplicații. 

Crearea, actualizarea și ștergerea datelor

După citirea cu succes a conținutului din back-end, veți crea, actualiza și șterge datele. Următorul exemplu va ilustra modul de actualizare a datelor, utilizând un exemplu controversat în care aplicația vă va permite să marcați un element ca fiind făcut prin atingerea în celulă. Rețineți collection.document (ID-ul itemului) .updateData (["făcut":! item.done]) proprietate de închidere, care face referință doar la un ID specific de document, actualizând fiecare dintre câmpurile din dicționar:

override func tableView (_tableView: UITableView, didSelectRowAt indexPath: IndexPath) lasa item = tasks [indexPath.row] let collection = Firestore.firestore () colectare ("Tasks") collection.document (item.id) ["done":! item.done,]) err in dacă err = err print ("Eroare la actualizarea documentului: \ (err)") else print (la: [indexPath], cu: .automatic)

Pentru a șterge un element, apelați document(ID-ul itemului).șterge() metodă:

override func tableView (_tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool return true suprascrie func tableView (_tableview: UITableView, comite editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) if (editingStyle ==delete)  permite item = tasks [indexPath.row] _ = Firestore.firestore () colecție ("Tasks") document (item.id) .delete ()

Crearea unei noi sarcini va implica adăugarea unui nou buton în Storyboard și conectarea acestuia IBAction la controlerul de vizualizare, creând un addTask (_ expeditor :) metodă. Când un utilizator apasă butonul, va afișa o foaie de alertă în care utilizatorul poate adăuga un nou nume de activitate:

colecție ("Sarcini"). addDocument (date: ["nume": textFieldReminder.text? "sarcină goală", "făcut": falsă)) 

Completați partea finală a aplicației introducând următoarele:

@IBAction func addTask (_ expeditor: Oricare) letarrtVC: UIAlertController = UIAlertController (titlu: "Noua sarcină", ​​mesaj: "Ce vreți să vă amintiți?"  a renunța la cancelAction = UIAlertAction.init (titlu: "Anulare", stil: .destructive, handler: nil) alertVC.addAction (cancelAction) // Alertă acțiune închidere permite addAction = UIAlertAction.init (titlu: "Adăugare", stil:. implicit) (UIAlertAction) -> Void in let textFieldReminder = (alertVC.textFields? .first)! ca UITextField permiteți db = Firestore.firestore () var docRef: DocumentReference? = eror = err (imprimanta) (de exemplu: "nu"), "Eroare la adăugarea documentului: \ (err)") altceva print ("Document adăugat cu ID: \ (docRef! .DocumentID)" alertVC.addAction (addAction) nil)

Construiți și rulați aplicația o dată în plus și, atunci când apare simulatorul, încercați să adăugați câteva sarcini, precum și să marcați câteva lucruri ca făcute și, în final, să testați funcția de ștergere eliminând unele sarcini. Puteți confirma că datele stocate au fost actualizate în timp real prin trecerea la consola bazei de date Firebase și respectarea colecției și a documentelor.

Filtrarea și interogările compuse

Până acum, ați lucrat doar cu o interogare simplă, fără capacități specifice de filtrare. Pentru a crea interogări ușor mai puternice, puteți filtra prin valori specifice utilizând o caracteristică a whereField clauză:

docRef.whereField ("nume", isEqualTo: searchString)

Puteți să vă ordonați și să limitați datele de interogare, utilizând formatul comandă (după:) și limitat la: ) după cum urmează:

docRef.order (de: "nume") limită (5)

În aplicația FirebaseDo, ați folosit deja limită cu interogarea de bază. În fragmentul de mai sus, ați utilizat de asemenea o altă caracteristică, interogări complexe, unde atât comanda, cât și limita sunt înlănțuite împreună. Aveți posibilitatea să lanțați cât mai multe interogări doriți, cum ar fi în următorul exemplu:

docRef .deField ("nume", isEqualTo: searchString) .deField ("done", isEqualTo: false) .order (de: "name") .limit

Concluzie

În acest tutorial, ați explorat noul produs MBaaS de la Google, Cloud Firestore, și în acest proces a creat o aplicație simplă de memento de sarcină care demonstrează cât de ușor este să persistenți, să vă sincronizați și să interogați datele din cloud. Ați învățat despre structura schemelor de date Firestore în comparație cu baza de date Firebase Realtime și despre modul de citire și scriere a datelor în timp real, precum și actualizarea și ștergerea datelor. De asemenea, ați învățat cum să efectuați interogări simple și complexe și cum să filtrați datele. 

Cloud Firestore a fost creat cu scopul de a asigura robustețea bazei de date Firebase Realtime fără multe dintre limitările pe care dezvoltatorii de telefonie mobilă trebuiau să le suporte, mai ales în ceea ce privește scalabilitatea și interogarea. Am doar zgâriat suprafața a ceea ce puteți realiza cu Firestore și merită să explorați câteva dintre conceptele mai avansate, cum ar fi Paginarea datelor cu Cursoare de interogare, Gestionarea indexurilor și securizarea datelor dvs..

Cod