iOS 9 Introducere în cadrul de contacte

Introducere

Cu iOS 9, OS X El Capitan și watchOS 2, Apple a introdus un nou cadru, Contacte. Acest cadru oferă o abordare orientată pe obiecte pentru a lucra cu informațiile de contact ale utilizatorului și înlocuiește funcția Carte de adrese cadru.

În acest tutorial, vom reimplementa funcționalitatea de bază a aplicației Contacts pe iOS, astfel încât să puteți afla cum funcționează aceste noi interfețe API.

Cerințe preliminare

Acest tutorial cere să executați Xcode 7+ pe OS X Yosemite sau mai târziu. De asemenea, va trebui să descărcați proiectul Starter de la GitHub.

1. Accesarea contactelor

Vom utiliza în primul rând cadrul de contacte pentru a accesa contactele utilizatorului și pentru a le afișa într-o vizualizare de tabel. Deschideți proiectul de pornire și mergeți la MasterViewController.swift.

Dacă derulați în partea de sus a fișierului, puteți vedea că am adăugat deja o declarație de import pentru cadrul de contact. Acest lucru ne oferă acces la clasele, protocoalele și constantele definite în cadrul.

importă contacte

În MasterViewController clasa, înlocuiți punerea în aplicare goală a getContacts () cu următoarele metode. Asigurați-vă că adăugați și retrieveContactsWithStore (_ :) metoda prezentată mai jos.

functieContacts, completeHandler: (autorizat: Bool, eroare: NSError?) -> Void in if authorized self.retrieveContactsWithStore (store)) altfel dacă CNContactStore.authorizationStatusForEntityType (.Contacts) == .Autorizat self.retrieveContactsWithStore (store)
funcția retrieveContactsWithStore (magazin: CNContactStore) do let groups = încercați store.groupsMatchingPredicate (nil) let predicate = CNContact.predicateForContactsInGroupWithIdentifier (grupuri [0] .identifier) [CNNetContactFormatter.descriptorForRequiredKeysForStyle (.FullName), CNContactEmailAddressesKey] contacte = încercați store.unifiedContactsMatchingPredicate (predicate, keysToFetch: keysToFetch) self.objects = contacte dispatch_async (dispatch_get_main_queue (), () -> Void in self.tableView.reloadData  captura print (eroare)

Să trecem prin acest pas pas cu pas. Creăm a CNContactStore și acest obiect este utilizat pentru a comunica direct cu sistemul de contacte din iOS. Apoi verificăm starea de autorizare a CNContactStore. Dacă este nedeterminat, solicităm autorizarea și preluăm contactele dacă reușim. Dacă aplicația este deja autorizată, preluăm imediat contactele utilizatorului.

În retrieveContactsWithStore (_ :) metodă, ne împachetăm codul într-un do-catch deoarece două dintre metodele pe care le folosim sunt metodele de aruncare. Puteți citi mai multe despre metodele de aruncare și tratarea erorilor pe Envato Tuts+.

În do clauza, vom prelua grupurile de contacte de pe dispozitiv. Utilizarea CNContact clasa, noi creăm un NSPredicate obiect care corespunde tuturor contactelor din cadrul primului grup pe care tocmai l-am recuperat.

Apoi creăm o matrice care conține un număr de taste constante. Aceste chei se referă direct la informațiile pe care le are și accesul la aplicație. Pentru orice taste pe care nu le specificați (de exemplu, numărul de telefon), aplicația dvs. nu va putea accesa aceste informații. Când lucrați cu cadrul de contacte, acesta este denumit a contact parțial deoarece nu aveți acces la toate informațiile despre un contact.

Utilizarea magazin obiect, vom prelua contactele care se potrivesc cu predicatul pe care l-am creat mai devreme și cu tastele specificate. Atribuiți rezultatul la controlerul de vizualizare obiecte array să fie afișat în vizualizarea tabelului. Aplicăm vizualizarea tabelului pentru a reîncărca firul principal. Acest lucru este important deoarece preluarea contactelor este efectuată pe un fir de fundal.

Există câteva aspecte cheie care trebuie luate în considerare:

  •  descriptorForRequiredKeysForStyle (_ :) clasa folosită pe CNContactFormatter este o modalitate convenabilă de a adăuga cu ușurință toate cheile necesare pentru a vizualiza numele unui contact.
  • Predicatul pe care îl creați nu trebuie să fie pentru un grup de contacte. Acesta poate fi unul dintre multe lucruri, inclusiv căutarea unui nume de potrivire, de exemplu.
lasa predicat = CNContact.predicateForContactsMatchingName ("John")
  • În cadrul Contacte, nu există nicio modalitate prin care aplicația dvs. să poată accesa direct fiecare persoană de contact. Din acest motiv, folosim codul de mai sus pentru a prelua primul grup de contacte, nu toate contactele.
  • Atunci când preluăm contactele, folosim unifiedContactsMatchingPredicate (_: keysToFetch :) metodă. Ce înseamnă "unificat" în acest context? Dacă un utilizator are mai multe persoane de contact care se referă la aceeași persoană, acestea pot să le conecteze împreună în aplicația Persoane de contact. Când aplicația dvs. încearcă să acceseze mai întâi contactele acestui utilizator, decât să returneze mai multe CNContact instanțe, cadrul de contacte unifică acestea împreună într-un singur obiect, astfel încât aplicația dvs. să poată afișa corect informațiile și să le interpreteze cu ușurință.

Apoi, trebuie să afișăm informațiile despre persoana de contact în ecranul de masă. În MasterViewController clasa, înlocuiască punerea în aplicare a tableView (_: cellForRowAtIndexPath :) cu urmatoarele:

suprascrie func tableView (tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell lasa celula = tableView.dequeueReusableCellWithIdentifier ("Cell", pentruIndexPath: indexPath) let contact = self.objects [indexPath.row] let formatter = CNContactFormatter .textLabel? .text = formatter.stringFromContact (contact) cell.detailTextLabel? .text = contact.emailAddresses.first ?.value ca? String retur cell

Folosim CNContactFormatter clasa pentru a prelua cu ușurință o Şir valoarea numelui contactului. De asemenea, primim prima adresă de e-mail pentru contact (reprezentată de CNLabeledValue obiect) și obțineți valoarea sa. A CNLabeledValue obiect reprezintă orice informație de contact în care poate fi necesară o informație contextuală. Aceste obiecte conțin doar o etichetă și o valoare. În exemplul următor, cuvintele din îndrăzneţ reprezintă eticheta unui articol și cuvintele din cursiv reprezintă valoarea lor.

  • Acasă adresa
  • Muncă telefon
  • Personal e-mail

Construiți și rulați aplicația în simulator. Când executați aplicația pentru prima dată, ar trebui să vedeți următoarea alertă.

După ce faceți clic O.K, vizualizarea tabelului ar trebui să afișeze un element după cum se arată mai jos.

Acum este momentul să completați vizualizarea detaliată când este selectat un contact din vizualizarea tabelului. La preluarea contactelor, am reținut doar suficiente chei pentru a accesa numele și adresele de e-mail ale unui contact. Pentru vizualizarea detaliată a aplicației noastre, dorim și să afișăm adresa, precum și o imagine de profil. Pentru a face acest lucru, am putea adăuga cheile suplimentare în MasterViewController clasă la preluarea contactelor. Cu toate acestea, vom relua același contact din nou cu cheile de care avem nevoie utilizând identificatorul contactului.

Deschis DetailViewController.swift și să înlocuiască punerea în aplicare a configureView () cu următoarele.

func configureView () // Actualizați interfața cu utilizatorul pentru elementul de detaliu. dacă permiteți oldContact = auto.contactItem let store = CNContactStore () nu let keysToFetch = [CNContactFormatter.descriptorForRequiredKeysForStyle (.FullName), CNContactEmailAddressesKey, CNContactPostalAddressesKey, CNContactImageDataKey, CNContactImageDataAvailableKey] let contact = try store.unifiedContactWithIdentifier (oldContact.identifier, keysToFetch: (date) auto.fullName.text = CNContactFormatter (date_date_date_main_queue (), () -> Void in if contact.imageDataAvailable  ) .stringFromContact (contact) self.email.text = contact.emailAddresses.first? .value ca? String dacă contact.isKeyAvailable (CNContactPostalAddressesKey) dacă permiteți adresa postalAddress = contact.postalAddresses.first? .value ca? CNPostalAddress auto.address .text = CNPostalAddressFormatter () stringFromPostalAddress (postalAddress) altceva self.address.text = "Nici o adresă") captura print (error)

Să lăsăm implementarea în jos. Obținem o referință dezbrăcată la elementul de contact primit de la MasterViewController și noi creăm un altul CNContactStore instanță.

În a do-catch declarație, noi creăm un altul keysToFetch array, de data aceasta cu tastele pentru adrese poștale, date imagine și date de imagine disponibile. Apoi folosim magazinul de contact pentru a prelua un nou CNContact instanță cu informațiile de care avem nevoie prin utilizarea unifiedContactWithIdentifier (_: keysToFetch :) metodă.

Din nou, rețineți că actualizăm interfața de utilizator pe firul principal. Verificăm să vedem dacă sau nu contactul are date de imagine disponibile pentru încărcare și transformă acest lucru într-un UIImage dacă este posibil. Populam Numele complet și e-mail etichete cu informațiile corecte.

Deși nu este strict necesar în acest exemplu, deoarece știm care sunt cheile disponibile, verificăm dacă aplicația noastră poate accesa sau nu informațiile despre adresele poștale ale contactului. Rețineți că acest pas este doar un exemplu, dar ar trebui să se facă întotdeauna cu persoanele de contact dacă nu sunteți sigur despre informațiile pe care le puteți accesa.

Descoperim prima adresă poștală a contactului (reprezentată de CNPostalAddress clasă) și să formateze acest lucru într - un șir folosind un CNPostalAddressFormatter instanță. CNPostalAddress clasa functioneaza similar cu CNContact dar are proprietăți diferite, cum ar fi strada, provincia și țara.

Construiți și rulați aplicația în simulator și selectați un contact din listă. Vizualizarea detaliată care apare ar trebui să arate cam așa:

2. Crearea și actualizarea contactelor

Pe lângă recuperarea contactelor, puteți crea și actualiza contacte existente utilizând CNMutableContact și CNSaveRequest clase. Deschis AddContactViewController.swift și înlocuiți a lua legatura proprietate cu următoarea implementare:

var contact: CNContact a se obține let store = CNContactStore () permite contactToAdd = CNMutableContact () contactToAdd.givenName = self.firstName.text ?? "" contactToAdd.familyName = auto.lastName.text ?? "" lasa mobileNumber = CNPhoneNumber (stringValue: (auto.mobileNumber.text ?? "")) lasa mobileValue = CNLabeledValue (eticheta: CNLabelPhoneNumberMobile, value: mobileNumber) contactToAdd.phoneNumbers = [mobileValue] valoare: (auto.homeEmail.text ?? "")) contactToAdd.emailAddresses = [email] dacă permiteți image = self.contactImage.image contactToAdd.imageData = UIImagePNGRpresentation (image) let saveRequest = CNSaveRequest () saveRequest.addContact contactToAdd, toContainerWithIdentifier: nil) nu try store.executeSaveRequest (saveRequest) captura print (error) return contactToAdd

Creăm a CNMutableContact obiect și a atribui a nume dat și nume de familie la el. Rețineți că folosim ?? sau un operator de colastare nul. În cazul în care valoarea din stânga lui ?? operatorul este zero, în schimb, este atribuită valoarea din dreapta.

Creăm a CNPhoneNumber obiect pentru a reprezenta numărul mobil introdus în câmpul de text. Apoi am pus acest număr în a CNLabeledValue obiect cu constanta CNLabelPhoneNumberMobile eticheta. Utilizarea CNPhoneNumber clasa este necesară deoarece numerele de telefon pot fi formate în mai multe moduri diferite într-o varietate de regiuni. Această clasă are un șir și creează o valoare a numărului de telefon pe care o poate lucra restul cadrului de contacte. mobileValue este apoi pus într-o matrice și atribuită contactului mutabil numere de telefon proprietate.

Noi creăm un lucru similar CNLabeledValue pentru e-mail, oferindu-i CNLabelHome eticheta. Această valoare este apoi atribuită contactului adrese de email proprietate. Verificăm să vedem dacă o imagine a fost atribuită persoanei de contact și, dacă este așa, să îi atribuie datele brute contactului imageData proprietate.

Pentru a salva contactul, creăm un CNSaveRequest obiect și numiți-l addContact (_: toContainerWithIdentifier :) metodă de a spune cadrului de contacte că dorim să creăm un contact nou. Trecând zero ca identificator, noul contact va fi salvat în grupul implicit de contacte.

In alt do-catch , spuneți magazinului de contact să execute cererea de salvare. În cele din urmă, returnează contactul nou creat pentru utilizare în restul aplicației.

Construiți și rulați aplicația dvs. și faceți clic pe butonul plus din colțul din dreapta sus pentru a adăuga un contact nou. Completați formularul, adăugați o fotografie și faceți clic pe Terminat. Noul contact trebuie apoi adăugat în vizualizarea de masă a controlerului de vizualizare master așa cum se arată mai jos.

Actualizarea unui contact existent este foarte asemănătoare cu crearea unui nou contact. Deși nu vom implementa acest lucru în aplicație, codul pentru actualizarea unui contact existent ar fi similar cu următorul:

(contactToUpdate = existingContact.mutableCopy () contactToUpdate.emailAddresses.append (CNLabelledValue (etichetă: CNLabelWork, valoare: emailToAdd)) saveRequest = CNSaveRequest () saveRequest.updateContact (contactToUpdate) try store.executeSaveRequest (saveRequest)

3. Contactați controlerul de vizualizare Picker

După cum am menționat în prima parte a acestui tutorial, cadrul de contacte nu are un API pentru accesarea directă a fiecărui contact de pe dispozitivul utilizatorului. Aceasta este pentru a proteja confidențialitatea utilizatorului, astfel încât aplicațiile să nu poată citi toate contactele și să colecteze informații.

Din fericire, cadrul oferă o UIViewController subclasă, CNContactPickerViewController, care oferă utilizatorului acces la toate contactele stocate pe dispozitiv.

Revedeți MasterViewController.swift și adăugați o declarație de import în partea de sus pentru ContactUI.

importați ContactsUI

Apoi, faceți MasterViewController clasa este conformă cu CNContactPickerDelegate protocol.

clasa MasterViewController: UITableViewController, CNContactPickerDelegate

Înlocuiți punerea în aplicare a addExistingContact () metodă a MasterViewController clasă cu următoarele:

func addExistingContact () permite contactPicker = CNContactPickerViewController () contactPicker.delegate = auto-auto.presentViewController (contactPicker, animat: true, completare: nil)

În cele din urmă, adăugați următoarea metodă a CNContactPickerDelegate protocol la MasterViewController clasă:

(contact: CNContact) NSNotificationCenter.defaultCenter () postNotificationName ("addNewContact", obiect: null, userInfo: ["contactToAdd": contact]

Construiți și rulați aplicația ultima oară și dați clic pe Adăugați existente în colțul din stânga sus. Ar trebui să apară un controler de vizualizare similar cu următorul:

Dacă este selectat un contact din controlerul de vizualizare a contactelor, controlerul de vizualizare respinge și contactul selectat este adăugat la vizualizarea de masă a controlerului de vizualizare master.

Controlerul de vizualizare a contactelor de selectare acceptă, de asemenea, mai multe selecții, în funcție de metodele pe care delegatul le implementează. De asemenea, poate fi personalizat pentru a accesa anumite proprietăți, precum și pentru a filtra contactele pe care le afișează pe baza predicatelor. Pentru mai multe informații, vă recomand să citiți CNContactPickerViewController clasa de referință și CNContactPickerDelegate referința protocolului.

Concluzie

După cum puteți vedea, noul cadru de contacte din iOS 9, OS X El Capitan și watchOS 2 este o colecție de API foarte bine concepută și ușor de utilizat. Acum ar trebui să fiți confortabil să accesați, să creați și să actualizați contactele pe dispozitivul unui utilizator. Ca întotdeauna, asigurați-vă că părăsiți comentariile și comentariile dvs. în comentariile de mai jos.

Cod