Arbeider med iCloud Dokumentoppbevaring

Å holde applikasjonsdata synkronisert på tvers av enheter er en komplisert og skremmende oppgave. Heldigvis er det akkurat hvorfor Apple bygget iCloud. I denne Tuts + Premium-serien lærer du hvordan iCloud fungerer, og hvordan programmene dine kan sømløst dele data på flere enheter.


Også tilgjengelig i denne serien:

  1. Arbeider med iCloud: Introduksjon
  2. Arbeide med iCloud: Nøkkelverdi Lagring
  3. Arbeider med iCloud: Dokumentoppbevaring
  4. Arbeider med iCloud: Core Data Integration

I den andre delen av denne serien viste jeg deg hvordan du kan utnytte iClouds nøkkelverdilagring for å holde små mengder brukerdata synkronisert over flere enheter. Selv om Key-Value Storage er enkelt å bruke og adoptere, er en av ulemper begrensningen i mengden data som kan lagres. Husk at hver applikasjon kun kan lagre 1MB data, og antallet av nøkkelverdier er begrenset til 1024. Som nevnt i slutten av den forrige veiledningen, kan bokmerkelederen vår komme inn i denne begrensningen hvis noen av brukerne ønsker å lagre mange bokmerker.

Løsningen på dette problemet skifter fra iCloud nøkkelverdi lagring til iCloud Document Storage for lagring av bokmerker. Når det gjelder diskplass, er iCloud Document Storage bare begrenset av brukerens iCloud-lagring. Å vite at en gratis konto leveres med 5 GB datalagring, er iCloud Document Storage den ideelle løsningen for vår bokmerkeforvalter. I denne veiledningen vil vi reflektere bokmerkestyreren fra å bruke iCloud Key Value Storage til å vedta iCloud Document Storage.


Før vi begynner

Jeg vil understreke at det er viktig at du har lest første og andre avdrag i denne serien før du leser dette stykket. I denne opplæringen vil vi refactor vår bokmerke leder ved å bygge på fundamentene vi lagt i del 2 av serien.


Et par ord om UIDocument

Med introduksjonen av iCloud gjorde Apple også UIDocument tilgjengelig for utviklere. Ingeniørene på Apple opprettet UIDocument med iCloud i tankene. UIDocument gjør iCloud-integrasjon for dokumentbasert applikasjon mye enklere. Det er imidlertid viktig å merke seg det UIDocument gjør mye mer enn å gi en enkel å bruke API for iCloud-integrasjon.

Dokumentbaserte applikasjoner må håndtere en rekke utfordringer, for eksempel (1) lese og skrive data fra og til disk uten å blokkere brukergrensesnittet, (2) lagre data til disk med passende intervaller, og (3) eventuelt integrere med iCloud. UIDocument gir innebygde løsninger for disse utfordringene.

Før vi begynner å jobbe med UIDocument, Jeg vil klargjøre hva UIDocument er og hva det ikke er. UIDocument er et kontrollerobjekt som styrer en eller flere modeller akkurat som UIViewController kontrollerer og styrer en eller flere visninger. UIDocument lagrer ingen data, men administrerer modellobjektene som holder brukerens data. Dette er et viktig konsept å forstå, som blir tydeligere når vi begynner å refactoring vår søknad til bruk UIDocument.

Et annet viktig konsept å forstå er hvordan lese- og skriveoperasjoner fungerer når de brukes UIDocument. Hvis du bestemmer deg for å bruke UIDocument i søknaden din trenger du ikke å bekymre deg for å blokkere hovedtråden når du leser eller skriver data til disk. Når du bruker UIDocument, operativsystemet håndterer automatisk en rekke oppgaver for deg i en bakgrunnskø og sørger for at hovedtråden forblir responsiv. Jeg vil gjerne ta et øyeblikk og forklare hver operasjon mer detaljert for å gi deg en god forståelse av de forskjellige bevegelige delene som er involvert.

La oss begynne med å lese data fra disk. Leseoperasjonen starter ved en åpen operasjon initiert på anropskøen. Den åpne operasjonen starter når et dokument åpnes ved å sende det en melding av openWithCompletionHandler:. Vi sender en fullføringshåndterer som påberopes når hele leseoperasjonen er ferdig. Dette er et viktig aspekt av lese- og skriveoperasjonen. Det kan ta en ikke-trivial tid å lese eller skrive dataene fra eller til disk, og vi vil ikke gjøre dette på hovedtråden og blokkere brukergrensesnittet. Den faktiske leseoperasjonen finner sted i en bakgrunnskø administrert av operativsystemet. Når leseoperasjonen er ferdig, vil loadFromContents: ofType: error: Metoden kalles på dokumentet. Denne metoden sender UIDocument dataene som er nødvendige for å initialisere modellen (e) den forvalter. Fullføringsbehandleren påberopes når denne prosessen er ferdig, noe som betyr at vi kan svare på lastingen av dokumentet ved for eksempel å oppdatere brukergrensesnittet med innholdet i dokumentet.


Skrivoperasjonen er lik. Den starter med en lagringsoperasjon initiert i kallekøen ved å sende saveToURL: forSaveOperation: completionHandler: til dokumentobjektet. Som med lesoperasjonen, passerer vi en ferdigstillingshåndterer som påberopes når skriveoperasjonen er ferdig. Skrive data til disk finner sted i en bakgrunnskø. Operativsystemet spør UIDocument for et øyeblikksbilde av modelldata ved å sende det en melding av contentsForType: error:. Fullføringsbehandleren påberopes når skriveoperasjonen er ferdig, noe som gir oss muligheten til å oppdatere brukergrensesnittet.


UIDocument er en grunnklasse og er ikke ment å bli brukt direkte. Vi må underklasse UIDocument og tilpasse den til våre behov. Med andre ord, vi underklasse UIDocument slik at den vet om modellen vår og hvordan den skal håndteres. I sin mest grunnleggende form, subclassing UIDocument krever bare at vi overstyrer loadFromContents: ofType: error: for lesing og contentsForType: error: for skriving.

Forvirret? Du bør være. Selv om UIDocument gjør livet mye lettere, det er en avansert klasse og vi arbeider med et komplekst emne. Imidlertid er jeg overbevist om at du vil få en god forståelse av dokumentbaserte applikasjoner når vi har refactored vår søknad.

Før vi fortsetter, vil jeg gjøre klart hva våre mål for denne opplæringen er. Det primære målet er å refactor vår søknad for å gjøre bruk av iCloud Document Storage i stedet for iCloud Key-Value Storage. Dette betyr at vi skal bruke UIDocument og subclass det for å passe våre behov. I tillegg skal vi lage en tilpasset modellklasse for vårt bokmerke som skal brukes og administreres av UIDocument underklasse.


Trinn 1: Konfigurere rettigheter

For øyeblikket er applikasjonen vår konfigurert til bare å bruke nøkkelverdig lagring. For å aktivere dokumentoppbevaring må vi først konfigurere programmets rettigheter. Åpne Målredigerer ved å velge vår søknad i Prosjektnavigator og velg det eneste målet fra mållisten. I rettigheter delen, bør du se iCloud Containere under iCloud Key Value Store. Listen ved siden av iCloud Containere er tom for øyeblikket. Klikk på pluss-knappen nederst på listen, og du vil se at Xcode oppretter en iCloud-beholderidentifikator for deg som samsvarer med applikasjonens pakkeidentifikator.

Hva er en iCloud-beholder? Som navnet antyder, er det en beholder i brukerens iCloud datalagring. Ved å spesifisere en (eller flere) iCloud-beholdere i programmets rettighetsfil, forteller vi operativsystemet hvilke beholdere vår søknad har tilgang til.



Trinn 2: Opprette bokmerkeklassen

I den forrige veiledningen lagret vi hvert bokmerke som en forekomst av NSDictionary, men dette er ikke en god løsning for en dokumentbasert applikasjon. I stedet vil vi opprette en egendefinert bokmerkeklasse som lar oss enkelt arkivere dataene sine.

Lage en ny NSObject underklasse ved å velge Fil fra menyen, velg Ny, og så Fil… . Å velge Kakao Touch fra venstre panel og velg Mål-C klasse fra listen over maler til høyre. Gi klassen et navn på Bookmark og sørg for at det er en underklasse av NSObject. Angi hvor du vil lagre den nye klassen og trykk Skape.



I vår modellens headerfil legger vi til de to egenskapene til bokmerkemodellen som vi brukte i den forrige opplæringen, a Navn og a URL. Begge egenskapene er forekomster av NSString. Vi erklærer også en utpekt initialiserer, som tar navn og en URL som parametere. Endelig er det viktig å sikre at vår Bookmark klassen stemmer overens med NSCoding protokollen.

 #importere  @interface bokmerke: NSObject  NSString * _name; NSString * _url;  @property (nonatomic, copy) NSString * navn; @property (nonatomic, copy) NSString * url; - (id) initWithName: (NSString *) navn ogURL: (NSString *) url; @slutt

I modellens implementeringsfil definerer vi først to konstanter for vårt bokmerke navn og URL. Dette er en god pratice, da det vil minimere sjansen for at vi mistype tastene som vi vil bruke kort tid. Deretter implementerer vi vår initialiseringsmetode. Denne metoden er grei. Vi initialiserer vår forekomst og tildeler navnet og nettadressen til våre variabler for bokmerkeeksempel.

Den viktige delen er å implementere de nødvendige metodene for å lage Bookmark klassen samsvarer med NSCoding protokoll. Hvis NSCoding protokollen er ny for deg, så oppfordrer jeg deg til å lese Programmeringsguiden for arkiver og serialiseringer, da dette er et viktig tema for enhver Cocoa-Touch-utvikler. Kjernen av det er at NSCoding protokollen tillater oss å enkelt arkivere og unarchive forekomster av Bookmark klasse.

 #import "Bookmark.h" #define kBookmarkName @ "Bookmark Name" #define kBookmarkURL @ "Bookmark URL" @implementation Bookmark @synthesize name = _name, url = _url; #pragma mark - #pragma mark Initialization - (id) initWithName: (NSString *) navn ogURL: (NSString *) url self = [super init]; hvis (selv) self.name = name; self.url = url;  returner selv;  #pragma mark - #pragma mark NSCoding Protocol - (void) encodeWithCoder: (NSCoder *) koder [coder encodeObject: selvnavn forKey: kBookmarkName]; [koder encodeObject: self.url forKey: kBookmarkURL];  - (id) initWithCoder: (NSCoder *) koder self = [super init]; hvis (selv! = null) self.name = [koder dekoderObjectForKey: kBookmarkName]; self.url = [coder dekoderObjectForKey: kBookmarkURL];  returner selv;  @slutt

Trinn 3: Subclassing UIDocument

subclassing UIDocument er ikke så vanskelig som du kanskje tror. Som nevnt tidligere, er alt vi trenger å gjøre overstyrt to metoder og opprette en eiendom for bokmerkemodellen den skal klare.

Opprett en ny klasse akkurat som vi gjorde for vår Bookmark klasse og gi det navnet på BookmarkDocument. Kontroller at det er en underklasse av UIDocument. I headerfilen til vår UIDocument underklasse, legger vi til en videresendelseserklæring for Bookmark klasse og vi lager en eiendom for vår bokmerke modell. Ikke glem å syntetisere accessors for denne eiendommen.

 #importere  @ klasse bokmerke; @interface BookmarkDocument: UIDocument Bookmark * _bookmark;  @property (nonatomic, strong) Bokmerke * bokmerke; @slutt

I implementeringsfilen importerer vi headerfilen til Bookmark klasse og definer en annen konstant for å tjene som nøkkel for arkivering og unarchiving av bokmerkemodellen. Som jeg nevnte tidligere, trenger vi bare å overstyre to metoder i UIDocument underklasse, (1) loadFromContents: ofType: error: og (2) contentsForType: error:. Den første metoden vil bli påkalt når vi åpner et dokument, mens den andre metoden vil bli påkalt når et dokument er lagret. Begge metodene kalles av operativsystemet. Vi trenger aldri å ringe disse mehodene direkte.

 #import "BookmarkDocument.h" #import "Bookmark.h" #define kArchiveKey @ "Bookmark" @implementation BookmarkDocument @synthesize bookmark = _bookmark;

La meg gå deg gjennom loadFromContents: ofType: error:. Det første argumentet er innhold av type id. Dette kan enten være en forekomst av NSData eller NSFileWrapper. Sistnevnte gjelder bare når applikasjonen bruker filpakker. I vårt tilfelle kan vi forvente en NSData forekomst. Vi sjekker først om lengden på NSData forekomsten er ikke lik null. Vi initialiserer en forekomst av NSKeyedUnarchiver og levere den med innhold gjenstand. Ved å dekode dataene, får vi en forekomst av Bookmark klassen tilbake. Dette er grunnen til at Bookmark klassen stemmer overens med NSCoding protokoll. Hvis lengden på NSData forekomsten er lik null, vi initialiserer et nytt bokmerke med standardverdier for navn og URL. Legg merke til at vi kommer tilbake JA på slutten av metoden.

 - (BOOL) loadFromContents: (id) content ofType: (NSString *) typeName error: (NSError * __ autoreleasing *) outError if ([innholdslengde]> 0) NSKeyedUnarchiver * unarchiver = [[NSKeyedUnarchiver allok] initForReadingWithData: innhold]; self.bookmark = [unarchiver dekodeObjectForKey: kArchiveKey]; [unarchiver finishDecoding];  else self.bookmark = [[Bookmark alloc] initWithName: @ "Bookmark Name" ogURL: @ "www.eksempel.com"];  returnere JA; 

De contentsForType: error: Metoden gjør det motsatte. Det vil si, vi leverer dataene som må skrives til disk. Denne dataobjektet er det såkalte øyeblikksbildet av modelldataene våre. Vi gjør dette ved å initialisere en forekomst av NSMutableData og bruk dette til å initialisere en forekomst av NSKeyedArchiver. Vi kan så arkivere vårt bokmerkefelt slik at det kan skrives til disk. Denne metoden forventer at vi skal returnere en forekomst av NSData og det er akkurat det vi gjør. Våre UIDocument Underklasse er nå klar for oss å bruke.

 - (id) contentForType: (NSString *) typeName error: (NSError * __ autoreleasing *) outError NSMutableData * data = [[NSMutableData alloker] init]; NSKeyedArchiver * archiver = [[NSKeyedArchiver allokere] initForWritingWithMutableData: data]; [arkiver encodeObject: self.bookmark forKey: kArchiveKey]; [arkiver ferdigKoding]; returnere data; 

Trinn 4: Refactoring View Controllers

Det er fire elementer i vår søknad som må refactored hvis vi ønsker å gjøre bruk av iCloud Document Storage:
(1) lasting, (2) visning, (3) lagring og (4) sletting av bokmerker. La oss begynne med å legge inn bokmerker.

Før vi tar en titt på loadBookmarks metode, må vi erklære en privat eiendom, en forekomst av NSMetadataQuery. Det vil bli klart hvorfor vi trenger å gjøre dette på bare noen få minutter. Ikke glem å legge til to ekstra importeringserklæringer til vår visningskontrollers implementasjonsfil, en for Bookmark klasse og en for BookmarkDocument klasse.

 #import "ViewController.h" #import "Bookmark.h" #import "BookmarkDocument.h" #import "AddBookmarkViewController.h" @interface ViewController () NSMetadataQuery * _query;  @property (nonatomic, strong) NSMetadataQuery * spørring; @end @implementation ViewController @synthesize bookmarks = _bookmarks; @synthesize tableView = _tableView; @synthesize query = _query;

Trinn 4A: Laster inn bokmerker

I stedet for NSDictionary forekomster, vår bokmerkeserie, vil datakilden til tabelloversikten inneholde forekomster av BookmarkDocument klasse. La oss ta en titt på refactored loadBookmarks metode. Vi starter med å initialisere bokmerkene. Deretter spør vi NSFileManagers for nettadressen til iCloud-beholderen vi vil bruke til å lagre våre bokmerker. Ikke kast bort den fargerike navnet på denne metoden. URLForUbiquityContainerIdentifier: aksepterer ett argument, identifikatoren til iCloud-beholderen vi ønsker å få tilgang til. Ved å overføre null som argumentet, NSFileManagers vil automatisk velge den første iCloud-beholderen som er deklarert i programmets rettighetsfil. Merk at hvis du angir en iCloud-beholderidentifikator, må du også gi teamidentifikatoren. Det riktige formatet er ..

 - (void) loadBookmarks if (! self.bookmarks) self.bookmarks = [[NSMutableArray alloc] init];  NSURL * baseURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier: null]; hvis (baseURL) self.query = [[NSMetadataQuery alloc] init]; [self.query setSearchScopes: [NSArray arrayWithObject: NSMetadataQueryUbiquitousDocumentsScope]]; NSPredicate * predicate = [NSPredicate predicateWithFormat: @ "% K som '*'", NSMetadataItemFSNameKey]; [self.query setPredicate: predicate]; NSNotificationCenter * nc = [NSNotificationCenter defaultCenter]; [nc addObserver: selvvelger: @selector (queryDidFinish :) navn: NSMetadataQueryDidFinishGatheringNotification object: self.query]; [nc addObserver: selector: @selector (queryDidUpdate :) navn: NSMetadataQueryDidUpdateNotification object: self.query]; [self.query startQuery]; 

Denne metoden er ikke bare for å finne ut hvor vi kan lagre våre iCloud-dokumenter. Ved å ringe denne metoden, vil operativsystemet utvide programmets sandkasse for å inkludere iCloud-containerkatalogen vi angav. Dette betyr at vi må ringe denne metoden før vi kan begynne å lese eller skrive data til denne katalogen. Hvis du skulle logge den returnerte nettadressen til konsollen, vil du legge merke til to rariteter, (1) den returnerte nettadressen for iCloud-containeren er en lokal nettadresse (finnes på selve enheten), og (2) denne lokale nettadressen lever ikke i søknadens sandkasse. Slik iCloud fungerer, er at vi lagrer dokumentene vi vil lagre i iCloud i denne lokale katalogen som NSFileManagers gir oss. ICloud-demonen, som kjører på enheten vår i bakgrunnen, vil ta vare på synkroniseringsaspektet av dokumentene, og det vil gjøre dette selv om programmet ikke kjører.

Fordi den lokale nettadressen lever utenfor søknadens sandkasse, må vi påberope denne metoden før vi leser eller skriver til denne katalogen. Ved å påkalle denne metoden spør vi operativsystemet for tillatelse til å lese og skrive til denne katalogen.

La oss fortsette å dissekere loadBookmarks metode. Vi bekrefter at nettadressen vi kommer tilbake fra NSFileManagers er ikke lik null. Sistnevnte innebærer to viktige ting, (1) vi har et sted som vi kan lese fra og skrive til og (2) iCloud er aktivert på enheten. Det andre punktet er spesielt viktig da ikke alle enheter vil ha iCloud aktivert.

Hvis NSFileManagers returnerte faktisk en gyldig nettadresse, vi initialiserer en forekomst av NSMetadataQuery og tilordne den til instansvariabelen vi erklærte tidligere. De NSMetadataQuery klassen tillater oss å søke iCloud-beholderen for dokumenter. Etter initialisering av en forekomst av NSMetadataQuery, Vi spesifiserer omfanget av vårt søk. I vårt tilfelle søker vi i dokumenter katalog av vår iCloud-beholder siden det er stedet der vi skal lagre bokmerkedokumenter. Du kan finjustere søket ved å angi et søkeprotikat. Hvis du er kjent med Core Data, er dette ikke nytt for deg. Vårt søk vil være enkelt, vi vil søke etter alle dokumentene i dokumentmappen til vår iCloud-beholder, derav stjernen i predikatet.

Før vi starter spørringen, er det viktig å innse at vi ikke bør forvente et øyeblikkelig resultat tilbake fra spørringen. I stedet registrerer vi visningskontrollen som observatør for NSMetadataQueryDidUpdateNotification og NSMetadataQueryDidFinishGatheringNotification varsler med spørringseksemplet som avsender. Dette betyr at vi vil bli varslet når spørringen har returnert noen resultater eller når resultatene er oppdatert. Til slutt begynner vi spørringen.

Det er viktig at vi holder en referanse til spørringseksemplet for å forhindre at det blir utgitt. Dette er grunnen til at vår visningskontroller holder en referanse til spørringen (som en forekomstvariabel) så lenge spørringen kjører.

La oss ta en titt på queryDidFinish: og queryDidUpdate: melding om tilbakeringingsmetoder for å se hvordan man håndterer resultatene av spørringen. Begge metodene overfører varselets avsenderobjekt, NSMetadataQuery eksempel, til en praktisk metode, processQueryResults:. Når vi ser på denne metoden, ser vi at vi først begynner å deaktivere oppdateringer for spørringen. Dette er viktig da resultatene av spørringen kan få live oppdateringer når endringer finner sted, og vi må forhindre det så lenge vi behandler spørringenes resultater. Deretter fjerner vi alle objekter fra bokmerkene og oppgir resultatene av spørringen. Hvert element i resultatlisten er en forekomst av NSMetadataItem, som inneholder metadata knyttet til hvert bokmerke dokument, inkludert filadressen vi trenger for å åpne dokumentet. Vi spør hver metadata-artikkel for filadressen og initierer det respektive dokumentet.

Vær oppmerksom på at initialisering av et bokmerke-dokument ikke betyr at vi har lastet det fra disken. Husk at dette er gjort ved å sende vårt bokmerkedokument en melding om openWithCompletionHandler:. Hvis den åpne operasjonen lykkes og dokumentet er lastet, legger vi det til vårt utvalg av bokmerker og viser det i tabellvisningen. Til slutt må vi fjerne visningskontrollen som observatør, da vi ikke lenger trenger å motta varsler på dette tidspunktet.

 - (void) queryDidFinish: (NSNotification *) varsel NSMetadataQuery * query = [varselobjekt]; // Stop Updates [query disableUpdates]; // Stopp forespørsel [spørre stopQuery]; // Fjern bokmerker [self.bookmarks removeAllObjects]; [query.results enumerateObjectsUsingBlock: ^ (id obj, NSUInteger idx, BOOL * stopp) NSURL * documentURL = [(NSMetadataItem *) obj valueForAttribute: NSMetadataItemURLKey]; BookmarkDocument * document = [[BookmarkDocument alloc] initWithFileURL: documentURL]; [dokument openWithCompletionHandler: ^ (BOOL suksess) hvis (suksess) [self.bookmarks addObject: dokument]; [self.tableView reloadData]; ]; ]; [[NSNotificationCenter defaultCenter] removeObserver: self]; 

Trinn 4B: Viser bokmerker i tabellvisningen

Koden for å vise bokmerkene i tabellvisningen trenger ikke å endres mye. I stedet for å hente riktig NSDictionary eksempel fra datakilden, henter vi en forekomst av BookmarkDocument klasse. Å få tilgang til navnet og nettadressen til bokmerket må også oppdateres.

 - (UITableViewCell *) tableView: (UITableView *) aTableView cellForRowAtIndexPath: (NSIndexPath *) indexPath statisk NSString * CellIdentifier = @ "Cell Identifier"; UITableViewCell * celle = [aTableView dequeueReusableCellWithIdentifier: CellIdentifier]; hvis (celle == nil) celle = [[UITableViewCell allokere] initWithStyle: UITableViewCellStyleSubtitle reuseIdentifier: CellIdentifier];  // Hent bokmerke BookmarkDocument * document = [self.bookmarks objectAtIndex: indexPath.row]; // Konfigurer Cell cell.textLabel.text = document.bookmark.name; cell.detailTextLabel.text = document.bookmark.url; returcelle; 

Trinn 4C: Lagre et bokmerke

Gå over til lagre: metode i AddBookmarkViewController. I stedet for å lage en NSDictionary og sender den til hovedvisningen kontrolleren, oppretter vi en ny Bookmark forekomst. Det er det. Resten håndteres i saveBookmark: metode for hovedvisningen kontrolleren. Ikke glem å legge til en importerklæring for Bookmark klasse.

 - (IBAction) lagre: (id) avsender Bookmark * bookmark = [[Bookmark alloc] initWithName: self.nameField.text andURL: self.urlField.text]; [self.viewController saveBookmark: bokmerke]; [self dismissViewControllerAnimated: JA ferdigstillelse: null]; 

Lagre et bokmerke til vår iCloud-beholder er nesten like enkelt som å lagre det i programmets sandkasse. Først spør vi NSFileManagers for nettadressen til vår iCloud-beholder som vi gjorde tidligere. Basert på denne nettadressen, konstruerer vi den riktige nettadressen for å lagre bokmerkedokumentet i dokumenter katalog over iCloud-beholderen. Navnet på dokumentet vårt kan være det vi vil at det skal være så lenge navnet er unikt. Jeg har valgt å bruke bokmerkeets navn og en tidsstempel. Brukeren vil ikke se dette filnavnet, så navnet er ikke så viktig. Det som er viktig er at det er unikt.

Vi har et bokmerkeinstans, men vi har ikke et bokmerke-dokument ennå. Vi lager et nytt bokmerke dokument ved å initialisere det med nettadressen vi nettopp har konstruert. Deretter tilordner vi vårt nye bokmerke til dokumentets bokmerkeegenskap. Til slutt legger vi til dokumentet i bokmerkene og laster opp tabellvisningen.

Lagring av dokumentet til iCloud-beholderen er enkelt. Vi initierer lagringsoperasjonen jeg snakket om tidligere ved å sende vårt nye dokument meldingen saveToURL: forSaveOperation: completionHandler:. Den andre parameteren i denne metoden angir typen lagringsoperasjon. I vårt tilfelle passerer vi UIDocumentSaveForCreating, som betyr å skape et helt nytt bokmerke dokument. Siden vi ikke trenger å gjøre noe spesielt i vårt eksempel, logger vi bare en melding til konsollen når lagringsoperasjonen er ferdig.

Du har kanskje lagt merke til at vår metodedeklarasjon endret seg noe. Vi overfører ikke lenger en forekomst av NSDictionary som det eneste argumentet. I stedet passerer vi en forekomst av Bookmark klasse. Pass på at du oppdaterer topptekstfilen for å gjenspeile denne endringen. Du må også legge til en foward-klassedeklarasjon for å forhindre at noen kompilervarsler vises. Dette er oppgaver som du bør være kjent med nå.

 - (void) saveBookmark: (Bookmark *) bokmerke // Lagre bokmerke NSURL * baseURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier: null]; hvis (baseURL) NSURL * documentsURL = [baseURL URLByAppendingPathComponent: @ "Dokumenter"]; NSURL * documentURL = [documentsURL URLByAppendingPathComponent: [NSString stringWithFormat: @ "Bookmark _% @ -% f", bookmark.name, [[NSDate date] timeIntervalSince1970]]]; BookmarkDocument * document = [[BookmarkDocument alloc] initWithFileURL: documentURL]; document.bookmark = bookmark; // Legg til bokmerke til bokmerker [self.bookmarks addObject: document]; // Oppdater tabelloversikt [self.tableView reloadData]; [dokument saveToURL: documentURL forSaveOperation: UIDocumentSaveForCreating completionHandler: ^ (BOOL suksess) hvis (suksess) NSLog (@ "Lagre lyktes.");  else NSLog (@ "Save failed."); ]; 

Trinn 4D: Slette bokmerker

Det siste manglende stykket av puslespillet er sletting av bokmerker. Dette er veldig enkelt i forhold til det vi har gjort hittil. Vi henter det riktige bokmerkedokumentet fra datakilden og forteller NSFileManagers for å slette den fra iCloud-beholderen ved å sende den riktige nettadressen. Dette vil også slette dokumentet på iCloud. Det er så enkelt det er. Selvfølgelig oppdaterer vi også datakilden og tabellvisningen.

 - (void) tableView: (UITableView *) aTableView commitEditingStyle: (UITableViewCellEditingStyle) editingStyle forRowAtIndexPath: (NSIndexPath *) indexPath if (editingStyle == UITableViewCellEditingStyleDelete) // Hent dokument BookmarkDocument * document = [self.bookmarks objectAtIndex: indexPath.row] ; // Slett dokument NSError * error = nil; hvis (! [[NSFileManager defaultManager] removeItemAtURL: document.fileURL feil: & error]) NSLog (@ "En feil oppstod under forsøk på å slette dokument. Feil% @ med brukerinfo% @.", feil, error.userInfo);  // Oppdater bokmerker [self.bookmarks removeObjectAtIndex: indexPath.row]; // Oppdater tabellvisning [aTableView deleteRowsAtIndexPaths: [NSArray arrayWithObject: indexPath] withRowAnimation: UITableViewRowAnimationFade]; 

Konklusjon

I denne opplæringen har vi refactored vår søknad om å bruke iCloud Document Storage i stedet for iCloud Key-Value Storage. Selv om vi har refactored ganske mye kode, var prosessen ganske enkel. Vi har nå en dokumentbasert applikasjon som er mye mer egnet for å håndtere større mengder brukerdata. De grunnleggende komponentene er på plass, og utvidelsen av applikasjonen krever liten innsats fra vår side. Vær oppmerksom på at vår søknad fortsatt er minimal implementering av en bokmerkebehandling. For eksempel er det ikke mulig å redigere bokmerker. Vi bør også gjøre mer feilkontroll hvis vi ønsker å gjøre søknaden til et robust og pålitelig program som er klar for utgivelse.

Du har kanskje også lagt merke til at vi har en rekke metoder som vi ikke trenger lenger. Jeg har fjernet disse metodene fra den endelige koden, og jeg foreslår at du gjør det samme. Fjerning av foreldet kode er også en del av refactoring-prosessen og viktig når du vil beholde koden din vedlikeholdsbar.

Neste gang

I denne veiledningen tok vi en nærmere titt på iCloud Document Storage, så vel som UIDocument klasse. I neste veiledning vil vi zoome inn på UIManagedDocument, en diskret underklasse av UIDocument designet for å jobbe tett med Core Data.