Komme i gang med Cloud Firestore for iOS

Mobilkodere har benyttet seg av Googles Mobile Backend as a Service (MBaaS) plattform Firebase Realtime Database i mange år, og hjelper dem med å fokusere på å bygge funksjoner for sine programmer uten å måtte bekymre seg om infrastruktur og database. Ved å gjøre det enkelt å lagre og vedvare data i skyen og ta vare på autentisering og sikkerhet, tillater Firebase kodere å fokusere på klientsiden. 

I fjor annonserte Google enda en back-end database løsning, Cloud Firestore, bygget fra grunnen opp med løftet om større skalerbarhet og intuitivitet. Dette introduserte imidlertid litt forvirring om stedet i forhold til Googles allerede eksisterende flaggskipprodukt, Firebase Realtime Database. Denne opplæringen vil skisse forskjellene mellom de to plattformene og de ulike fordelene ved hver. Du vil lære å jobbe med Firestore-dokumentreferanser, samt lese, skrive, oppdatere og slette data i sanntid, ved å bygge en enkel påminnelsesapp.

Målet med denne opplæringen

Denne opplæringen vil avsløre deg til Cloud Firestore. Du lærer å utnytte plattformen for sanntidsdatabaseutholdenhet og synkronisering. Vi vil dekke følgende emner:

  • Hva Cloud Firestore er
  • Firestore datamodellen
  • sette opp Cloud Firestore
  • skaper og jobber med Cloud Firestore referanser
  • leser data i sanntid fra Cloud Firestore
  • opprette, oppdatere og slette data
  • filtrering og sammensatte spørringer

Forutsatt kunnskap

Denne opplæringen forutsetter at du har hatt noen eksponering for Firebase og en bakgrunn som utvikler seg med Swift og Xcode.

Hva er Cloud Firestore?

Firestore, som Firebase Realtime Database, tilbyr mobil- og webutviklere en kryssplattformløsningsløsning for å vedvare data i sanntid, uavhengig av nettverkslatens eller internett-tilkobling, samt sømløs integrasjon med produktserien Google Cloud Platform. Sammen med disse likhetene er det forskjellige fordeler og ulemper som skiller seg fra hverandre. 

Datamodell

På grunnleggende nivå lagrer Realtime Database data som et stort, monolitisk, hierarkisk JSON-tre, mens Firestore organiserer data i dokumenter og samlinger, samt subsamlinger. Dette krever mindre denormalisering. Lagring av data i ett JSON-tre har fordelene ved enkelhet når det gjelder å jobbe med enkle datakrav. Det blir imidlertid mer besværlig i skala når man arbeider med mer komplekse hierarkiske data. 

Frakoblet støtte

Begge produktene tilbyr offline-støtte, aktivt caching data i køer når det er latent eller ingen nettverkstilkobling - synkronisering av lokale endringer tilbake til bakenden når det er mulig. Firestore støtter offline synkronisering for webprogrammer i tillegg til mobilapper, mens Realtime-databasen bare aktiverer mobilsynkronisering.

Spørsmål og transaksjoner 

Realtime Database støtter bare begrenset sorterings- og filtreringsfunksjoner - du kan bare sortere eller filtrere på et eiendomsnivå, men ikke begge, i en enkelt spørring. Spørsmål er også dype, noe som betyr at de returnerer et stort under-tre med resultater tilbake. Produktet støtter bare enkle skrive- og transaksjonsoperasjoner som krever fullført tilbakeringing. 

Firestore, derimot, introduserer indeksforespørsler med sammensatt sortering og filtrering, slik at du kan kombinere handlinger for å lage kjedelfiltre og sortering. Du kan også utføre grunne spørsmål som returnerer undersamlinger i stedet for hele samlingen du vil få med Realtime Database. Transaksjoner er atomariske, uansett om du sender en batchoperasjon eller single, med transaksjoner som gjentas automatisk til slutt. I tillegg støtter Realtime Database bare individuelle skrivetransaksjoner, mens Firestore gir batchoperasjoner atomvist.

Ytelse og skalerbarhet

Realtime-databasen, som du forventer, er ganske robust og har lav latens. Databaser er imidlertid begrenset til enkelte regioner, med forbehold om zonal tilgjengelighet. Firestore, derimot, huser data horisontalt over flere soner og regioner for å sikre sann global tilgjengelighet, skalerbarhet og pålitelighet. Faktisk har Google lovet at Firestore vil være mer pålitelig enn Realtime Database. 

En annen mangel på Realtime Database er begrensningen til 100 000 samtidige brukere (100 000 samtidige tilkoblinger og 1000 skriver / sekund i en enkelt database), hvoretter du må kaste databasen din (del databasen din i flere databaser) for å støtte flere brukere . Firestore skalerer automatisk over flere forekomster uten at du trenger å gripe inn. 

Firestore er utformet fra grunnen med skalerbarhet, og har en ny skjematisk arkitektur som replikerer data på tvers av flere regioner, tar seg av autentisering og håndterer andre sikkerhetsrelaterte forhold alt innenfor SDK-klientens side. Den nye datamodellen er mer intuitiv enn Firebase, som mer ligner på andre sammenlignbare NoSQL-databaseløsninger som MongoDB, samtidig som den gir en mer robust spørringsmotor. 

Sikkerhet 

Endelig styrer Realtime Database, som du vet fra våre tidligere opplæringsprogrammer, sikkerhet gjennom kaskaderegler med separate valideringsutløsere. Dette fungerer med Firebase Database Rules, og validerer dataene dine separat. Firestore, derimot, gir en enklere, men mer kraftfull sikkerhetsmodell som utnytter Cloud Firestore Security Rules og Identity and Access Management (IAM), med data validering unntatt automatisk.

Firestore Data Model

Firestore er en NoSQL-dokumentbasert database, bestående av samlinger av dokumenter, som hver inneholder data. Siden det er en NoSQL-database, vil du ikke få tabeller, rader og andre elementer du vil finne i en relationsdatabase, men i stedet sett av nøkkel / verdipar som du finner i dokumenter. 

Du oppretter dokumenter og samlinger implisitt ved å tilordne data til et dokument, og hvis dokumentet eller samlingen ikke eksisterer, blir det automatisk opprettet for deg, da samlingen alltid må være root (første) node. Her er en enkel oppgaveeksempel på prosjektet du vil jobbe med på kort tid, bestående av oppgaveroppsamlingen, samt tallrike dokumenter som inneholder to felt, navnet (strengen) og et flagg for om oppgaven er ferdig (boolsk).

La oss dekomponere hvert element slik at du kan forstå dem bedre. 

samlinger

Synonym med databasetabeller i SQL-verdenen inneholder samlinger ett eller flere dokumenter. Samlinger må være hovedelementene i skjemaet ditt og kan bare inneholde dokumenter, ikke andre samlinger. Du kan imidlertid referere til et dokument som i sin tur refererer til samlinger (subsamlinger).

I diagrammet ovenfor består en oppgave av to primitive felt (navn og ferdig), samt en subsamling (deloppgave) som består av to primitive felt. 

dokumenter

Dokumenter består av nøkkel / verdi par, med verdiene som har en av følgende typer: 

  • primitive felter (for eksempel strenger, tall, boolean)
  • komplekse nestede objekter (lister eller arrays av primitiver)
  • sub-samlinger

Nestede objekter kalles også kart og kan representeres som følger, innenfor dokumentet. Følgende er et eksempel på en nestet objekt og array, henholdsvis:

ID: 2422892 // primitivt navn: "Husk å kjøpe melk" detalj: // nested object notes: "Dette er en oppgave å kjøpe melk fra butikken" opprettet: 2017-04-09 på grunn: 2017-04-10 ferdig: falsk varsling: ["2F22-89R2", "L092-G623", "H00V-T4S1"] ... 

Hvis du vil ha mer informasjon om de støttede datatyper, kan du se dokumentasjonen til datatyper i Google. Deretter skal du sette opp et prosjekt for å jobbe med Cloud Firestore.

Sette opp prosjektet

Hvis du har jobbet med Firebase før, bør mye av dette være kjent for deg. Ellers må du opprette en konto i Firebase, og følg instruksjonene i avsnittet "Oppsett av prosjektet" i vår tidligere opplæring, Kom i gang med Firebase-godkjenning for iOS . 

For å følge med denne opplæringen klone du opplæringsprosjektet repo. Neste, ta med Firestore biblioteket avlegger til følgende i din Podfile:

pod 'Firebase / Core' pod 'Firebase / Firestore'

Skriv inn følgende i terminalen din for å bygge biblioteket ditt:

pod installasjon

Deretter bytt til Xcode og åpne opp .xcworkspace fil. Naviger til AppDelegate.swift fil og skriv inn følgende i applikasjons: didFinishLaunchingWithOptions: metode:

FirebaseApp.configure ()

I nettleseren din, gå til Firebase-konsollen og velg database fanen til venstre. 

Pass på at du velger alternativet til Start i testmodus slik at du ikke har noen sikkerhetsproblemer mens vi eksperimenterer, og følg sikkerhetsmeldingen når du flytter appen din til produksjon. Du er nå klar til å lage en samling og noen eksempler på dokumenter.

Legge til et samlings- og eksempeldokument

For å starte, lag en innledende samling, oppgaver, ved å velge Legg til samling knapp og navngi samlingen, som illustrert nedenfor:

For det første dokumentet skal du forlate Dokument ID-blanket, som automatisk genererer en ID for deg. Dokumentet består ganske enkelt av to felt: Navn og ferdig.

Lagre dokumentet, og du bør kunne bekrefte samlingen og dokumentet sammen med den automatisk genererte IDen:

Med databasen satt opp med et eksempeldokument i skyen, er du klar til å begynne å implementere Firestore SDK i Xcode.

Opprette og arbeide med databasehenvisninger

Åpne opp MasterViewController.swift fil i Xcode og legg til følgende linjer for å importere biblioteket:

importere Firebase klasse MasterViewController: UITableViewController @IBOutlet weak var addButton: UIBarButtonItem! private var-dokumenter: [DocumentSnapshot] = [] offentlige varoppgaver: [Oppgave] = [] privat var lytter: ListenerRegistration! ... 

Her oppretter du bare en lyttervariabel som lar deg utløse en forbindelse til databasen i sanntid når det er en endring. Du lager også en DocumentSnapshot referanse som vil holde midlertidig data øyeblikksbilde.

Før du fortsetter med visningskontrolleren, opprett en annen rask fil, Task.swift, som vil representere datamodellen din:

import Stiftelsens struktur Oppgave var navn: String var ferdig: Bool var id: String var ordbok: [String: Any] return ["navn": navn, "ferdig": ferdig) forlengelsesoppgave init? [String: Any], id: String) guard la navnet = ordbok ["navn"] som? String, la gjort = ordbok ["ferdig"] som? Bool annet return nil self.init (navn: navn, ferdig: ferdig, id: id)

Kodestykket ovenfor inneholder en bekvemmelighetsegenskap (ordbok) og metode (init) som gjør det enklere å populere modellobjektet. Bytt tilbake til visningsregulatoren, og erklære en global settervariabel som vil begrense basespørsmålet til de øverste 50 oppføringene i oppgavelisten. Du vil også fjerne lytteren når du angir spørringsvariabelen, som angitt i didSet eiendom nedenfor:

fileprivate func baseQuery () -> Query return Firestore.firestore (). samling ("Oppgaver") .grense (til: 50) Fileprivat var spørring: Spørsmål? didSet hvis la lytter = lytter listener.remove () overstyr func viewDidLoad () super.viewDidLoad () self.query = baseQuery () overstyr func viewWillDisappear (_ animert: Bool) super.viewWillDisappear animert) self.listener.remove ()

Lese data i sanntid fra Cloud Firestore

Med dokumentreferansen på plass, i viewWillAppear (_animated: Bool), knytte lytteren du opprettet tidligere med resultatet av spørreskjemaet, og hente en liste over dokumenter. Dette gjøres ved å ringe Firestore-metoden spørre? .addSnapshotListener:

self.listener = query? .addSnapshotListener (dokumenter, feil) i vakt la snapshot = dokumenter ellers print ("Feil henter dokumenter resultater: \ (feil!)" return la results = snapshot.documents.map  ) -> Oppgave i hvis la oppgave = Oppgave (ordbok: document.data (), id: document.documentID) returneringsoppgave else fatalError ("Kan ikke initialisere type \ (Task.self) med ordbok \ data ()) ") self.tasks = resultater self.documents = snapshot.documents self.tableView.reloadData ()

Lukkingen over tildeler snapshot.documents ved å kartlegge arrayet iterativt og pakke det til en ny Oppgave modelleksemplarobjekt for hvert dataobjekt i øyeblikksbildet. Så med bare noen få linjer har du lykkes å lese i alle oppgavene fra skyen og tilordne dem til det globale oppgavermatrise. 

For å vise resultatene, fyll ut følgendeTableviewdelegere metoder:

overstyr func numberOfSections (i tableView: UITableView) -> Int return 1 overstyr func tableView (_ tableView: UITableView, numberOfRowsInSectionseksjon: Int) -> Int return tasks.count overstyr func tableView (_ tableView: UITableView, cellForRowAt indexPath : IndexPath) -> UITableViewCell la cellen = tableView.dequeueReusableCell (withIdentifier: "Cell", for: indexPath) la element = oppgaver [indexPath.row] cell.textLabel! .Text = item.name cell.textLabel! .TextColor = item.done == false? UIColor.black: UIColor.lightGray returcelle

På dette stadiet skal du bygge og kjøre prosjektet, og i simulatoren bør du kunne observere data som vises i sanntid. Legg til data via Firebase-konsollen, og du bør se det vises øyeblikkelig i app simulatoren. 

Opprette, oppdatere og slette data

Etter å ha lest innholdet fra baksiden, har du lyst til å lese, oppdatere og slette data. Det neste eksemplet vil illustrere hvordan du oppdaterer data, ved hjelp av et utvalgt eksempel hvor appen bare lar deg merke et element som gjort ved å trykke på cellen. Legg merke til collection.document (item.id) .updateData (["ferdig":! item.done]) nedleggingsegenskap, som bare refererer til et bestemt dokument ID, oppdaterer hvert felt i ordboken:

overstyr func tableView (_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) la item = oppgaver [indexPath.row] la collection = Firestore.firestore (). samling ("Oppgaver") collection.document (item.id) .updateData ( ["ferdig":! item.done,]) err i hvis la err = err print ("Feil oppdateringsdokument: \ (err)") ellers print ("Document successfully updated") tableView.reloadRows (på: [indexPath], med: .automatic)

For å slette et element, ring dokument(item.id) .Delete () metode:

overstyr func tableView (_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool return true tilsidesatte func tableView (_ tableView: UITableView, commit redigeringStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) if (edititingStyle == .delete)  la element = oppgaver [indexPath.row] _ = Firestore.firestore (). samling ("Oppgaver"). dokument (item.id) .delete ()

Opprette en ny oppgave vil innebære å legge til en ny knapp i Storyboard og koble til den IBAction til visningskontrolleren, opprette en addTask (_ sender :) metode. Når en bruker trykker på knappen, vil den få et varselark der brukeren kan legge til et nytt oppgavenavn:

samling ("Oppgaver"). addDocument (data: ["navn": textFieldReminder.text ?? "empty task", "done": false)) 

Fullfør den siste delen av appen ved å skrive inn følgende:

@IBAction func addTask (_ sender: Any) la alertVC: UIAlertController = UIAlertController (tittel: "Ny oppgave", melding: "Hva vil du huske?", PreferredStyle: .alert) alertVC.addTextField (UITextField)  la cancelAction = UIAlertAction.init (tittel: "Cancel", stil: .destructive, handler: null) alertVC.addAction (cancelAction) // Alert action closure la addAction = UIAlertAction.init (tittel: "Legg til", stil:. standard) (UIAlertAction) -> Ugyldig i la textFieldReminder = (alertVC.textFields? .first)! som UITextField la db = Firestore.firestore () var docRef: DocumentReference? = null docRef = db.collection ("Oppgaver"). addDocument (data: ["navn": textFieldReminder.text ?? "tom oppgave", "ferdig": falsk]) err i hvis la err = err print "Feil ved å legge til dokument: \ (err)") annet print ("Dokument lagt med ID: \ (docRef! .DocumentID") alertVC.addAction (addAction) til stede (alertVC, animert: true, completion: null)

Bygg og kjør appen en gang til, og når simulatoren vises, kan du prøve å legge til noen få oppgaver, samt merke noen som gjort, og til slutt teste slettingsfunksjonen ved å fjerne noen oppgaver. Du kan bekrefte at de lagrede dataene har blitt oppdatert i sanntid ved å bytte til Firebase-databasekonsollen og observere samlingen og dokumentene.

Filtrering og sammensatte spørringer

Så langt har du bare jobbet med et enkelt søk uten noen spesifikke filtreringsegenskaper. For å lage litt mer robuste spørringer, kan du filtrere etter bestemte verdier ved å bruke a whereField klausul:

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

Du kan bestille og begrense søkedataene dine ved å benytte deg av rekkefølge etter: ) og grense (til:) metoder som følger:

docRef.order (ved: "navn") .grense (5)

I FirebaseDo-appen har du allerede brukt grense med basen spørringen. I den ovennevnte koden har du også brukt en annen funksjon, sammensatte spørringer, hvor både ordre og grense er sammenkalt. Du kan kjede så mange spørringer som du vil, for eksempel i følgende eksempel:

docRef .whereField ("navn", isEqualTo: searchString) .whereField ("done", isEqualTo: false) .order (av: "navn") .limit (5)

Konklusjon

I denne opplæringen har du utforsket Googles nye MBaaS-produkt, Cloud Firestore, og i prosessen opprettet en enkel oppgavepåminnelsesapp som demonstrerer hvor lett det er for deg å fortsette, synkronisere og spørre dataene dine i skyen. Du lærte om Firestores dataskjema struktur i forhold til Firebase Realtime Database, og hvordan du leser og skriver data i sanntid, samt oppdaterer og sletter data. Du lærte også hvordan du utfører enkle så vel som sammensatte spørringer, og hvordan du filtrerer data. 

Cloud Firestore ble opprettet med sikte på å gi robustheten til Firebase Realtime Database uten mange av de begrensningene mobile utviklere måtte tåle, spesielt når det gjelder skalerbarhet og spørring. Vi bare kløftet overflaten av hva du kan oppnå med Firestore, og det er absolutt verdt å utforske noen av de mer avanserte konseptene, for eksempel Pagineringsdata med Query Cursors, Managing Indexes og Sikring av dataene dine..