Persistența și Sandboxing-ul pe iOS

Datele persistente din lansările de aplicații sunt o cerință pe care cele mai multe aplicații iOS o au, de la stocarea preferințelor utilizatorilor utilizând sistemul implicit al utilizatorilor la gestionarea seturilor de date mari într-o bază de date relațională. În acest articol, vom explora cele mai comune strategii utilizate pentru stocarea datelor într-o aplicație iOS. Voi vorbi, de asemenea, despre sistemul de fișiere pe iOS și despre modul în care aplicația sandbox afectează persistența datelor.


Introducere

Ați parcurs un drum lung, lăcuste și ați învățat multe. Cu toate acestea, există un aspect vital al dezvoltării iOS pe care nu am discutat încă, persistența datelor. Practic fiecare aplicație iOS stochează date pentru utilizare ulterioară. Datele pe care aplicațiile dvs. iOS le stochează pot fi orice, de la preferințele utilizatorilor la cache-urile temporare sau chiar la seturile de date relaționale mari.

Înainte de a discuta despre cele mai comune strategii de persistență a datelor pe care dezvoltatorii le au pe platforma iOS, am să petrec mai întâi câteva minute discutând despre sistemul de fișiere și despre conceptul de sandboxing al aplicației. Chiar credeți că ați putea să stocați datele aplicației dvs. ori de câte ori doriți în sistemul de fișiere? Gândește-te din nou, padawan.


Sistem de fișiere și Sandbox pentru aplicații

Securitatea pe platforma iOS a fost una dintre prioritățile de vârf ale Apple încă de la introducerea iPhone-ului în 2007. Spre deosebire de aplicațiile OS X, o aplicație iOS este plasată într-un sandbox pentru aplicații. Spre deosebire de ceea ce cred majoritatea oamenilor, sandbox-ul unei aplicații nu se referă numai la directorul unei aplicații de tip sandbox din sistemul de fișiere. Aplicația sandbox conține, de asemenea, acces controlat și limitat la datele de utilizator stocate pe dispozitiv, serviciile de sistem și hardware.

Odată cu introducerea Mac App Store, Apple a început să impună aplicarea sandbox-urilor pe OS X, de asemenea. Chiar dacă constrângerile aplicate aplicațiilor OS X nu sunt la fel de stricte ca cele impuse aplicațiilor iOS, conceptul general este similar, dar nu identic. Aplicația de tip sandbox a unei aplicații iOS, de exemplu, conține pachetul de aplicații, care nu este valabil pentru aplicațiile OS X. Motivele acestor diferențe sunt în principal istorice.

Sandboxing și directoare

Sistemul de operare instalează fiecare aplicație iOS într-un director de nisip, care conține directorul pachetului de aplicații și trei directoare suplimentare, Documente, Bibliotecă, și tmp. Directorul de nisip al aplicației, denumit adesea ca fiind Acasă director, pot fi accesate prin apelarea unei simple funcții a Fundației, NSHomeDirectory ().

NSLog (@ "HOME>% @", NSHomeDirectory ());

Puteți încerca singur. Creați un nou proiect Xcode bazat pe Vizualizare individuală șablon și numește-l Persistența datelor.

Deschis TSPAppDelegate.m și adăugați fragmentul de cod de mai sus aplicare: didFinishLaunchingWithOptions:.

Dacă rulați aplicația în Simulatorul iOS, ieșirea din consola va arăta ca ieșirea prezentată mai jos.

2014-03-27 09: 48: 16.794 Persistența datelor [1426: 60b] HOME> / Utilizatori / Bart / Bibliotecă / Suport de aplicații / Simulator iPhone / 7.1 / Aplicații / 5024403A-C65E-44DD-BCD2-F93097FB502E

Cu toate acestea, dacă executați aplicația pe un dispozitiv fizic, ieșirea pare puțin diferită, după cum puteți vedea mai jos. Aplicația sandbox și limitările impuse sunt totuși identice.

2014-03-27 09: 48: 51.571 Persistența datelor [1426: 60b] HOME> / var / mobile / Aplicații / A4D17A73-84D7-4628-9E32-AEFEA5EE6153

Preluarea căii spre aplicație Documente directorul necesită un pic mai mult de lucru, după cum puteți vedea în fragmentul de cod de mai jos.

NSArray * directoare = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES); NSString * documents = [directoare firstObject]; NSLog (@ "DOCUMENTS>% @", documente);

Noi folosim NSSearchPathForDirectoriesInDomains () funcționează și trece NSDocumentDirectory constant ca primul argument pentru a indica faptul că suntem interesați doar de cererea Documente director. Al doilea și al treilea argument sunt mai puțin importante pentru această discuție. Funcția returnează o instanță din NSArray care conține un rezultat, calea spre aplicație Documente director.

S-ar putea să te întrebi de ce folosesc firstObject in loc de objectAtIndex: pentru a prelua primul și singurul obiect din matricea căilor. Chiar dacă pot fi destul de sigur că matricea returnată nu este goală, dacă matricea ar fi goală și matricea ar primi un mesaj de objectAtIndex: cu un argument de 0, aplicația s-ar prăbuși din cauza unei excepții neobosite.

Sunând firstObject pe matrice, matricea se întoarce zero dacă nu conține obiecte, ceea ce înseamnă că nu ar fi aruncat nici o excepție. Ține minte că documentația este prietenul tău.

De ce Sandboxing?

Care este beneficiul sandboxing-ului? Motivul principal al aplicațiilor pentru sandboxuri este securitatea. Prin limitarea aplicațiilor la propriul lor spațiu de lucru, aplicațiile compromise nu pot provoca deteriorarea sistemului de operare sau a altor aplicații.

De compromis aplicații, vreau să spun atât aplicații care au fost hacked, aplicații care sunt intenționat malware, precum și aplicații care conțin bug-uri critice care ar putea provoca daune din greșeală.

Chiar dacă aplicațiile sunt sandboxed pe platforma iOS, aplicațiile iOS pot solicita accesul la anumite fișiere sau active care se găsesc în afara spațiului de lucru al aplicației prin intermediul unui număr de interfețe de sistem.

Un exemplu este biblioteca muzicală stocată pe un dispozitiv iOS. Știți totuși că cadrele de sistem sunt responsabile de orice operațiuni legate de fișiere în astfel de ocazii.

Ce merge acolo?

Chiar dacă puteți face tot ceea ce doriți în sandbox-ul aplicației dvs., Apple a oferit câteva linii directoare cu privire la ceea ce ar trebui să fie stocat acolo. Este important să știți despre aceste linii directoare din mai multe motive. Atunci când un dispozitiv iOS are copii de rezervă de iTunes, nu toate fișierele dintr-o cutie de memorie a unei aplicații sunt incluse în copia de rezervă.

tmp directorul, de exemplu, ar trebui să fie utilizat numai pentru stocarea temporară a fișierelor. Sistemul de operare este liber să descarce acest director în orice moment, de exemplu, când dispozitivul are un spațiu redus pe disc. tmp directorul nu este inclus în backups.

Documente directorul este destinat datelor de utilizator, în timp ce Bibliotecă este utilizat pentru datele de aplicație care nu sunt strict legate de utilizator. Caches director în Bibliotecă directorul este un alt director care nu este susținut de iTunes.

De asemenea, rețineți că aplicația dvs. nu trebuie să modifice conținutul directorului pachet de aplicații. Directorul pachetului de aplicații este semnat când aplicația este instalată. Prin modificarea conținutului directorului pachetului de aplicații în orice mod, semnătura menționată mai sus este modificată, ceea ce înseamnă că sistemul de operare nu permite lansarea aplicației din nou. Aceasta este o altă măsură de securitate pusă în aplicare de Apple pentru a proteja consumatorii.


Opțiuni de persistență a datelor

Există mai multe strategii pentru stocarea datelor de aplicație pe disc. În acest articol, analizăm pe scurt patru abordări comune pe iOS:

  • setările utilizatorului
  • lista de proprietăți
  • SQLite
  • Datele principale

Opțiunile descrise în acest articol nu ar trebui considerate interschimbabile. Fiecare strategie are avantajele sale, precum și dezavantajele sale. Să începem să aruncăm o privire asupra sistemului implicit al utilizatorului.


Setări implicite utilizator

Sistemul implicit pentru utilizatori este ceva ce iOS a moștenit de pe sistemul OS X. Chiar dacă a fost creat și proiectat pentru stocarea preferințelor utilizatorului, acesta poate fi utilizat pentru stocarea oricăror tipuri de date atâta timp cât este vorba de un tip de listă de proprietăți, NSString, NSNumber, NSDate, NSArray, NSDictionary, și NSData, sau oricare dintre variantele lor mutabile.

Baza de date implicită a utilizatorului nu este decât o colecție de liste de proprietăți, o listă de proprietăți per aplicație. Lista de proprietăți este stocată într-un folder numit Preferințe în aplicație Bibliotecă , care indică scopul și funcția listei de proprietăți.

Unul dintre motivele pentru care dezvoltatorii consideră sistemul implicit pentru utilizatori este că este atât de ușor de utilizat. Uitați-vă la fragmentul de cod de mai jos pentru a vedea ce vreau să spun.

NSUserDefaults * userDefaults = [NSUserDefaults standardUserDefaults]; [userDefaults setBool: DA pentruKey: @ "Key1"]; [userDefaults setInteger: 123 pentruKey: @ "Key2"]; [userDefaults setObject: @ "Unele obiecte" pentruKey: @ "Key3"]; [userDefaults boolForKey: @ "Key1"]; [userDefaults integerForKey: @ "Key2"]; [userDefaults objectForKey: @ "Key3"]; [sincronizați userDefaults];

Apelând standardUserDefaults clasa pe NSUserDefaults, se returnează o referință la obiectul implicit implicit.

În ultimul rând, sunăm sincroniza pe obiectul implicit partajat pentru a scrie orice modificări pe disc. Este rareori necesară invocarea sincroniza, deoarece sistemul implicit de utilizator salvează modificările atunci când este necesar. Cu toate acestea, dacă stocați sau actualizați o setare utilizând sistemul implicit pentru utilizatori, uneori poate fi util sau necesar să salvați în mod explicit modificările pe disc.

La prima vedere, sistemul implicit al utilizatorului nu pare să fie altceva decât un magazin cu valoare cheie localizat la o anumită locație. Însă NSUserDefaults clasa, definită în cadrul Fundației, este mai mult decât o interfață pentru gestionarea unui magazin cheie-valoare. Aruncati o privire la referinta de clasa pentru mai multe informatii.

Înainte de a trece mai departe, lipiți fragmentul de cod de mai sus în delegatul aplicației aplicare: didFinishLaunchingWithOptions: și rulați aplicația în simulatorul iOS. Deschideți o nouă fereastră Finder și navigați la Bibliotecă> Suport de aplicații> Simulator iPhone> 7.1> Aplicații (a inlocui "7.1" cu cea mai recentă versiune de iOS).

Găsiți dosarul aplicației care corespunde aplicației, inspectând diferitele dosare numite criptic în Aplicații pliant. Folderul numit criptic este de fapt directorul sandbox al aplicației. În directorul sandbox pentru aplicații, deschideți Preferințe folder, situat în Bibliotecă și inspectați conținutul acestuia.

Ar trebui să vedeți o listă de proprietăți cu un nume identic cu identificatorul pachetului aplicației. Acesta este magazinul implicit pentru utilizator pentru aplicația dvs..

Dacă doriți să faceți mai ușor accesul la mediul de nisip al unei aplicații din Simulatorul iOS, vă recomandăm să vă uitați la SimPholders. Este un utilitar gratuit care face lucrul cu Simulatorul iOS mult mai ușor.


Lista de proprietăți

Am acoperit deja listele de proprietăți din această serie. De fapt, magazinul de backing al bazei de date implicite a utilizatorului este o listă de proprietăți. Utilizarea listelor de proprietăți este o strategie convenabilă pentru stocarea și extragerea unui grafic de obiecte. Liste de proprietăți au fost în jur de vârste, sunt ușor de folosit și, prin urmare, sunt o opțiune excelentă pentru stocarea datelor într-o aplicație iOS.

După cum am menționat mai devreme, este important să rețineți că o listă de proprietăți poate să stocheze numai datele din lista de proprietăți. Acest lucru înseamnă că nu este posibil să stocați obiecte model personalizate utilizând listele de proprietăți? Nu, este posibil. Cu toate acestea, obiectele model personalizate trebuie să fie arhivate - o formă de serializare - înainte ca acestea să poată fi stocate într-o listă de proprietăți. Arhivarea unui obiect înseamnă simplu că obiectul trebuie să fie convertit la un tip de date care poate fi stocat într-o listă de proprietăți, cum ar fi un NSData instanță.

Arhivarea obiectelor

Vă amintiți NSCoding protocol definit în cadrul Fundației? NSCoding protocol definește două metode,initWithCoder: și encodeWithCoder:, pe care o clasă trebuie să le implementeze pentru a permite instanțelor clasei să fie codificate și decodificate.

Codificarea și decodarea sunt mecanismele care stau la baza arhivării și distribuției obiectului. Cum vor funcționa obiectele de arhivare a obiectelor un pic mai târziu în această serie. În această lecție, vă arăt doar cum să scrieți matrice și dicționare pe disc folosind listele de proprietăți.

Scrierea în Dosar

Următorul fragment de cod vă va oferi o idee despre cât de ușor este să scrieți un disc sau un dicționar pe disc. În teorie, graficul obiect stocat într-o listă de proprietăți poate fi la fel de complex sau de mare pe cât doriți. Cu toate acestea, ține cont de faptul că listele de proprietate nu sunt menite pentru a stoca zeci sau sute de megabytes de date, încercând să le utilizeze în acest mod va duce probabil la performanțe degradate.

NSArray * fructe = @ [@ "Apple", @ "Mango", @ "Ananas", @ "prune", @ "caise"]; NSString * filePathFruits = [documente stringByAppendingPathComponent: @ "fruits.plist"]; [fructe writeToFile: filePathFruits atomic: YES]; NSDictionary * miscDictionary = @ @ "anArray": fructe, @ "anumber": @ 12345, @ "aBoolean": @YES; NSString * filePathDictionary = [documente stringByAppendingPathComponent: @ "misc-dictionary.plist"]; [miscDictionary writeToFile: filePathDictionary atomic: DA]; NSArray * loadedFruits = [NASrray arrayWithContentsOfFile: filePathFruits]; NSLog (@ "Fruits Array>% @", fructe încărcate); NSDictionary * loadedMiscDictionary = [dicționar NSDictionaryWithContentsOfFile: filePathDictionary]; NSLog (@ "Dicționar misc>% @", încărcatMiscDictionary);

Să aruncăm o privire la fragmentul de cod de mai sus. Începem prin stocarea unei referințe la o matrice literală într-o variabilă numită fructe. Creați calea fișierului pentru stocarea listei de proprietăți pe care urmează să o facem. Calea fișierului este creată prin adăugarea unui șir la calea fișierului Documente , pe care am reluat-o mai devreme în această lecție. Șirul pe care îl adăugăm va fi numele listei de proprietăți, inclusiv extensia sa, .plist-pe care o vom crea într-o secundă.

Scrierea matricei pe disc este la fel de ușor ca și apelarea writeToFile: atomically: pe matrice. Puteți să ignorați atomically pentru moment.

După cum ilustrează exemplul, scrierea unui dicționar pe disc urmează un model similar. Exemplul ilustrează, de asemenea, modul de creare a tabelelor și a dicționarelor dintr-o listă de proprietăți, dar aceasta este ceva deja acoperit anterior în această serie.

Rulați aplicația în Simulatorul iOS și navigați la aplicația Documente așa cum am văzut mai devreme. În acest director, ar trebui să vedeți cele două liste de proprietăți pe care tocmai le-am creat.


SQLite

Dacă aplicația dvs. este bazată pe date și funcționează cu cantități mari de date, atunci este posibil să doriți să căutați în SQLite. Ce este SQLite? Conținutul de pe site-ul web SQLite citește "Mic. Rapid, fiabil, alegeți oricare trei", care îl compară frumos.

SQLite este o bibliotecă care implementează o bază de date relațională încastrată. După cum sugerează și numele, se bazează pe standardul SQL (Limba de interogare structurată) la fel ca MySQL și PostgreSQL.

Principala diferență cu alte baze de date SQL este că SQLite este portabil, foarte ușor și că este fără server în loc de un proces separat accesat din aplicația client. Cu alte cuvinte, este încorporat în aplicație și, prin urmare, foarte rapid.

Site-ul SQLite pretinde că este cea mai răspândită bază de date SQL. Nu știu dacă este cazul, dar este cu siguranță o alegere populară pentru stocarea datelor de la client. Aperture și iPhoto, de exemplu, se bazează pe SQLite pentru o parte din stocarea datelor.

Avantajul SQLite de a lucra direct cu obiectele este că SQLite este ordine de mărime mai rapidă, ceea ce se datorează în mare măsură modului în care bazele de date relaționale și limbile de programare orientate pe obiecte diferă fundamental.

Pentru a reduce decalajul dintre SQLite și Obiectiv-C, un număr de Object Maparea relațională (ORM) au fost create în timp. ORM pe care Apple a creat-o pentru iOS și OS X este numit Datele principale, pe care o vom examina mai târziu în această lecție.

Flying Carne FMDB

Folosirea SQLite pe iOS înseamnă a lucra cu o bibliotecă bazată pe C. Dacă preferați o soluție orientată spre obiecte, atunci vă recomandăm învelișul obiectivului Gus Mueller (Flying Meat, Inc.) pentru SQLite, FMDB.

Aceasta face ca lucrul cu SQLite să fie mult mai ușor dacă preferați o interfață orientată pe obiecte. Biblioteca sprijină ARC (Numărătoarea automată a referințelor) din cutie și este foarte performant. Am folosit FMDB în trecut și am fost foarte mulțumiți de API și de robustețea și fiabilitatea bibliotecii.


Datele principale

Dezvoltatorii noi pentru datele de bază adesea înșeală datele de bază pentru o bază de date, în timp ce într-adevăr este o soluție de mapare relațională obiect creată și întreținută de Apple. Matt Gallagher a scris un mesaj minunat despre diferențele dintre Core Data și o bază de date. Datele de bază oferă un model orientat pe obiecte relaționale care poate fi serializat într-un magazin XML, binar sau SQLite. Datele principale suportă chiar și un magazin în memorie.

De ce ar trebui să utilizați datele de bază în loc de SQLite? Prin a pune această întrebare, vă presupuneți în mod eronat că baza de date este o bază de date. Avantajul utilizării datelor de bază este că lucrați cu obiecte în loc de date brute, cum ar fi rânduri dintr-o bază de date SQLite sau date stocate într-un fișier XML. Chiar dacă Core Data a avut câțiva ani dificili când a fost lansat în primul rând, a crescut într-un cadru robust, cu o mulțime de caracteristici, cum ar fi migrările automate, urmărirea modificărilor, faultului, și validare integrate.

O altă caracteristică excelentă pe care mulți dezvoltatori o apreciază este editorul de date Core Data construit în Xcode, care permite dezvoltatorilor modelul modelului lor de date printr-o interfață grafică.

Dacă datele de bază reprezintă soluția potrivită pentru aplicația dvs., depinde de datele pe care intenționați să le gestionați, atât din punct de vedere al cantității cât și al modelului care stau la baza. Dacă intenționați să gestionați seturi de date extrem de mari, atunci datele de bază pot deveni o problemă de performanță în timp. În acest caz, SQLite poate fi o soluție mai bună.


icloud

Probabil ați auzit de iCloud și s-ar putea să vă întrebați unde iCloud se încadrează în povestea persistenței datelor. iCloud nu este o formă de persistență a datelor cum ar fi SQLite sau Core Data. În schimb, este o platformă sau serviciu pentru a face datele de utilizator disponibile pe mai multe dispozitive și mai multe instanțe ale unei aplicații - sau chiar o familie de aplicații.

Platforma iCloud cuprinde mai multe servicii sau componente. Componenta care ne interesează este stocarea iCloud, care include trei tipuri de stocare:

  • stocare cheie-valoare
  • stocarea documentelor
  • Stocarea principalelor date.

Dacă doriți să citiți mai multe despre iCloud Storage, recomand să citiți o serie despre iCloud Storage pe care am scris-o mai devreme în acest an.

Concluzie

Acum ar trebui să aveți o idee bună despre opțiunile pe care le aveți în ceea ce privește persistența datelor atunci când le dezvoltați pentru platforma iOS. Rețineți că nu toate strategiile pe care le-am abordat sunt egale.

Această serie se apropie încet. În următoarele două rate, vom crea o altă aplicație pentru a pune în practică ceea ce am învățat până acum. Cel mai bun mod de a învăța este prin a face.

Cod