Met iOS 9, OS X El Capitan en watchOS 2 heeft Apple een geheel nieuw kader geïntroduceerd, Contacten. Dit raamwerk biedt een objectgerichte benadering van het werken met de contactgegevens van de gebruiker en vervangt de functiegebaseerde Adresboek kader.
In deze zelfstudie gaan we de basisfunctionaliteit van de app Contacten op iOS opnieuw implementeren, zodat u kunt leren hoe deze nieuwe API's werken.
Deze tutorial vereist dat je Xcode 7+ draait op OS X Yosemite of hoger. Je zult ook het startersproject van GitHub moeten downloaden.
We gaan eerst het contactframework gebruiken om toegang te krijgen tot de contacten van de gebruiker en deze weer te geven in een tabelweergave. Open het startersproject en ga naar MasterViewController.swift.
Als u naar de bovenkant van het bestand bladert, kunt u zien dat ik al een importinstructie voor het contactraamwerk heb toegevoegd. Dit geeft ons toegang tot de klassen, protocollen en constanten die in het kader zijn gedefinieerd.
contactpersonen importeren
In de MasterViewController
klasse, vervang de lege implementatie van de getContacts ()
methode met het volgende. Zorg ervoor dat u ook het retrieveContactsWithStore (_ :)
methode hieronder weergegeven.
func getContacts () let store = CNContactStore () if CNContactStore.authorizationStatusForEntityType (.Contacts) ==. NotDetermined store.requestAccessForEntityType (.Contacts, completionHandler: (authorized: Bool, error: NSError?) -> Void in indien toegestaan self.retrieveContactsWithStore (store)) else if CNContactStore.authorizationStatusForEntityType (.Contacts) == .Authorized self.retrieveContactsWithStore (store)
func retrieveContactsWithStore (winkel: CNContactStore) do let groups = try store.groupsMatchingPredicate (nil) let predicate = CNContact.predicateForContactsInGroupWithIdentifier (groups [0] .identifier) // let predicate = CNContact.predicateForContactsMatchingName ("John") laat keysToFetch = [CNContactFormatter.descriptorForRequiredKeysForStyle (.FullName), CNContactEmailAddressesKey] laat contacten = probeer store.unifiedContactsMatchingPredicate (predicate, keysToFetch: keysToFetch) self.objects = contacts dispatch_async (dispatch_get_main_queue (), () -> Void in self.tableView.reloadData () ) catch print (error)
Laten we deze code stap voor stap doorlopen. We creëren een CNContactStore
instance en dit object wordt gebruikt om rechtstreeks met het Contacts-systeem op iOS te communiceren. We controleren vervolgens de autorisatiestatus van CNContactStore
. Als dit niet wordt bepaald, vragen we om autorisatie en halen we de contacten op als dit lukt. Als de toepassing al is geautoriseerd, halen we onmiddellijk de contacten van de gebruiker op.
In de retrieveContactsWithStore (_ :)
methode, verpakken we onze code in a doe-vangst
verklaring omdat twee van de methoden die we gebruiken methoden zijn om te gooien. Je kunt meer lezen over werpmethoden en foutafhandeling op Envato Tuts+.
In de do
clausule halen we de contactgroepen op het apparaat. De ... gebruiken CNContact
klas, we maken een NSPredicate
object dat overeenkomt met alle contacten binnen de eerste groep die we zojuist hebben opgehaald.
Vervolgens maken we een array met een aantal constante sleutels. Deze toetsen hebben rechtstreeks betrekking op de informatie die uw app ook heeft. Voor alle sleutels die u niet opgeeft (bijvoorbeeld telefoonnummer), heeft uw app geen toegang tot die informatie. Bij het werken met het raamwerk voor contactpersonen wordt dit een a gedeeltelijk contact omdat u geen toegang hebt tot alle informatie van een contactpersoon.
De ... gebruiken op te slaan
object, halen we de contactpersonen op die overeenkomen met het predicaat dat we eerder hebben gemaakt en met de opgegeven sleutels. We wijzen het resultaat toe aan de view controller's voorwerpen
matrix die moet worden weergegeven in de tabelweergave. We dwingen de tabelweergave om opnieuw te laden in de hoofdthread. Dit is belangrijk omdat het ophalen van de contacten wordt uitgevoerd op een achtergrondthread.
Er zijn een paar belangrijke dingen om op te letten:
descriptorForRequiredKeysForStyle (_ :)
klassemethode gebruikt CNContactFormatter
is een handige manier om eenvoudig alle sleutels toe te voegen die nodig zijn om de naam van een contact te bekijken.let predicate = CNContact.predicateForContactsMatchingName ("John")
unifiedContactsMatchingPredicate (_: keysToFetch :)
methode. Wat betekent 'verenigd' in deze context? Als een gebruiker meerdere contactpersonen heeft die betrekking hebben op dezelfde persoon, kunnen ze deze koppelen aan de app Contacten. Wanneer uw app toegang probeert te krijgen tot de contacten van deze gebruiker in plaats van meerdere te retourneren CNContact
voorbeelden, het raamwerk van contactpersonen verenigt deze samen in één object zodat uw app informatie correct kan weergeven en gemakkelijk kan interpreteren.Vervolgens moeten we de contactgegevens van de contactpersoon weergeven in de tabelweergave. In de MasterViewController
klasse, vervang de implementatie van tableView (_: cellForRowAtIndexPath :)
met het volgende:
override func tableView (tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell let cell = tableView.dequeueReusableCellWithIdentifier ("Cell", forIndexPath: indexPath) laat contact = self.objects [indexPath.row] laat formatter = CNContactFormatter () cel .textLabel? .text = formatter.stringFromContact (contact) cell.detailTextLabel? .text = contact.emailAddresses.first? .value as? Stringretourcel
We maken gebruik van de CNContactFormatter
klasse om gemakkelijk een te halen Draad
waarde van de naam van het contact. We krijgen ook het eerste e-mailadres voor het contact (weergegeven door een CNLabeledValue
object) en krijgt zijn waarde. EEN CNLabeledValue
object staat voor contactinformatie waar een stukje contextuele informatie nodig kan zijn. Deze objecten bevatten slechts één label en één waarde. In het volgende voorbeeld, woorden in stoutmoedig vertegenwoordigen het label van een item en de woorden erin cursief vertegenwoordigen hun waarde.
Bouw en run uw app in de simulator. Wanneer u de app voor de eerste keer uitvoert, ziet u de volgende waarschuwing.
Na het klikken op OK, in de tabelweergave moet een item worden weergegeven zoals hieronder wordt weergegeven.
Het is nu tijd om de detailweergave in te vullen wanneer een contact wordt geselecteerd uit de tabelweergave. Bij het ophalen van de contactpersonen hebben we alleen voldoende sleutels opgehaald om toegang te krijgen tot de naam en e-mailadressen van een contactpersoon. Voor de detailweergave van onze app willen we ook hun adres en een profielfoto weergeven. Om dit te doen, kunnen we de extra sleutels toevoegen in de MasterViewController
klasse bij het ophalen van de contacten. We gaan echter hetzelfde contact opnieuw ophalen met de sleutels die we nodig hebben door de ID van het contact te gebruiken.
Open DetailViewController.swift en vervang de implementatie van configureView ()
met het volgende.
func configureView () // Update de gebruikersinterface voor het detailitem. indien oldContact = self.contactItem let store = CNContactStore () do let keysToFetch = [CNContactFormatter.descriptorForRequiredKeysForStyle (.FullName), CNContactEmailAddressesKey, CNContactPostalAddressesKey, CNContactImageDataKey, CNContactImageDataAvailableKey] laat contact = try store.unifiedContactWithIdentifier (oldContact.identifier, keysToFetch: keysToFetch) dispatch_async (dispatch_get_main_queue (), () -> Void in if contact.imageDataAvailable if let data = contact.imageData self.contactImage.image = UIImage (data: data) self.fullName.text = CNContactFormatter ( ) .stringFromContact (contact) self.email.text = contact.emailAddresses.first? .value as? String if contact.isKeyAvailable (CNContactPostalAddressesKey) if postalAddress = contact.postalAddresses.first? .value as? CNPostalAddress self.address .text = CNPostalAddressFormatter (). stringFromPostalAddress (postalAddress) else self.address.text = "Geen adres") catch print (error)
Laten we de implementatie verbreken. We krijgen een onverpakte verwijzing naar het contactitem dat is ontvangen van de MasterViewController
en we creëren een andere CNContactStore
aanleg.
In een doe-vangst
verklaring, we creëren een andere keysToFetch
matrix, dit keer met de sleutels voor postadressen, afbeeldingsgegevens en afbeeldingsgegevens beschikbaar. Vervolgens gebruiken we de contactopslag om een nieuw op te halen CNContact
bijvoorbeeld met de informatie die we nodig hebben door de unifiedContactWithIdentifier (_: keysToFetch :)
methode.
Nogmaals, merk op dat we de gebruikersinterface op de hoofdthread updaten. We controleren om te zien of de contactpersoon afbeeldingsgegevens beschikbaar heeft om te laden en dit in een te veranderen UIImage
object indien mogelijk. We vullen het voor-en achternaam
en e-mail
labels met de juiste informatie.
Hoewel dit in dit voorbeeld niet strikt noodzakelijk is, omdat we weten welke sleutels beschikbaar zijn, controleren we of onze app toegang heeft tot de postadressen van de contactpersoon. Merk op dat deze stap slechts een voorbeeld is, maar altijd moet worden gedaan met contactpersonen als u niet zeker weet welke informatie u kunt gebruiken.
We halen het eerste postadres van de contactpersoon op (vertegenwoordigd door de CNPostalAddress
class) en formatteer dit in een string met een CNPostalAddressFormatter
aanleg. De CNPostalAddress
klasse functioneert op dezelfde manier als de CNContact
klasse, maar het heeft verschillende eigenschappen, zoals straat, provincie en land.
Bouw en run uw app in de simulator en selecteer een contact uit de lijst. De detailweergave die verschijnt, zou er ongeveer zo uit moeten zien:
Naast het ophalen van contactpersonen kunt u ook bestaande contacten maken en bijwerken met behulp van de CNMutableContact
en CNSaveRequest
klassen. Open AddContactViewController.swift en vervang de contact
eigendom met de volgende implementatie:
var contact: CNContact get let store = CNContactStore () laat contactToAdd = CNMutableContact () contactToAdd.givenName = self.firstName.text ?? "" contactToAdd.familyName = self.lastName.text ?? "" laat mobileNumber = CNPhoneNumber (stringValue: (self.mobileNumber.text ?? "")) laat mobileValue = CNLabeledValue (label: CNLabelPhoneNumberMobile, waarde: mobileNumber) contactToAdd.phoneNumbers = [mobileValue] laat email = CNLabeledValue (label: CNLabelHome, value: (self.homeEmail.text ?? "")) contactToAdd.emailAddresses = [email] indien let image = self.contactImage.image contactToAdd.imageData = UIImagePNGRepresentation (image) let saveRequest = CNSaveRequest () saveRequest.addContact ( contactToAdd, toContainerWithIdentifier: nil) do try store.executeSaveRequest (saveRequest) catch print (error) return contactToAdd
We creëren een CNMutableContact
object en wijs een toe gegeven naam
en achternaam
ernaar toe. Merk op dat we de ??
of nul coalescerende operator. Als de waarde links van de ??
operator is nul
, de waarde aan de rechterkant wordt toegewezen.
We creëren een CNPhoneNumber
object om het mobiele nummer weer te geven dat is ingevoerd in het tekstveld. Vervolgens zetten we dit nummer in een CNLabeledValue
object met de constante CNLabelPhoneNumberMobile
label. Het gebruik van de CNPhoneNumber
Klasse is vereist omdat telefoonnummers op veel verschillende manieren in verschillende regio's kunnen worden opgemaakt. Deze klasse neemt een tekenreeks en maakt een telefoonnummerwaarde die met de rest van het kader van Contactpersonen kan worden gebruikt. De mobileValue
wordt vervolgens in een array geplaatst en toegewezen aan de veranderlijke contactpersonen telefoonnummers
eigendom.
We creëren een vergelijkbare CNLabeledValue
voor de e-mail, waardoor het de CNLabelHome
label. Deze waarde wordt vervolgens toegewezen aan de contactpersonen e-mailadressen
eigendom. We controleren om te zien of een afbeelding aan de contactpersoon is toegewezen en, zo ja, om zijn onbewerkte gegevens toe te wijzen aan de contactpersonen imageData
eigendom.
Om de contact op te slaan, maken we een CNSaveRequest
object en bel het Cont.persToev (_: toContainerWithIdentifier :)
methode om het raamwerk voor contactpersonen te vertellen dat we een nieuw contact willen maken. Door te passeren nul
als de identifier wordt de nieuwe contactpersoon opgeslagen in de standaardcontactgroep.
In een andere doe-vangst
verklaring, vertellen we de contactopslag om het opslagverzoek uit te voeren. Ten slotte retourneren we de nieuw gemaakte contactpersoon voor gebruik in de rest van de app.
Bouw en voer uw app uit en klik op de plusknop in de rechterbovenhoek om een nieuw contact toe te voegen. Vul het formulier in, voeg een foto toe en klik op Gedaan. Uw nieuwe contact moet dan worden toegevoegd aan het tabeloverzicht van de masterview-controller, zoals hieronder wordt weergegeven.
Het bijwerken van een bestaande contactpersoon lijkt sterk op het maken van een nieuw contact. Hoewel we dit niet in de app implementeren, lijkt de code voor het bijwerken van een bestaand contact op het volgende:
laattactToUpdate = existingContact.mutableCopy () contactToUpdate.emailAddresses.append (CNLabeledValue (label: CNLabelWork, value: emailToAdd)) laat saveRequest = CNSaveRequest () saveRequest.updateContact (contactToUpdate) try store.executeSaveRequest (saveRequest)
Zoals ik al zei in het eerste deel van deze tutorial, heeft het framework voor contactpersonen geen API voor directe toegang tot elk contact op het apparaat van de gebruiker. Dit is om de privacy van de gebruiker te beschermen, zodat apps niet al hun contacten kunnen lezen en informatie kunnen verzamelen.
Gelukkig biedt het framework een UIViewController
subklasse, CNContactPickerViewController
, die de gebruiker toegang geeft tot alle contacten die op het apparaat zijn opgeslagen.
opnieuw bezoeken MasterViewController.swift en voeg bovenaan een import-statement toe voor ContactUI.
import ContactsUI
Maak vervolgens de MasterViewController
klasse conform de CNContactPickerDelegate
protocol.
class MasterViewController: UITableViewController, CNContactPickerDelegate
Vervang de implementatie van de addExistingContact ()
methode van de MasterViewController
les met het volgende:
func addExistingContact () let contactsPicker = CNContactPickerViewController () contactPicker.delegate = self self.presentViewController (contactPicker, geanimeerd: true, completion: nil)
Voeg ten slotte de volgende methode toe van de CNContactPickerDelegate
protocol bij de MasterViewController
klasse:
func contactPicker (picker: CNContactPickerViewController, didSelectContact contact: CNContact) NSNotificationCenter.defaultCenter (). postNotificationName ("addNewContact", object: nil, userInfo: ["contactToAdd": contact])
Bouw en voer uw app een laatste keer uit en klik op Bestaande toevoegen in de linkerbovenhoek. Er moet een weergavecontroller worden weergegeven die lijkt op het volgende:
Als een contactpersoon in de view picker-weergaveregelaar is geselecteerd, wordt de weergavecontroller verwijderd en wordt de geselecteerde contactpersoon toegevoegd aan de tabelweergave van de masterview-controller.
De view picker-weergaveregelaar ondersteunt ook meerdere selecties, afhankelijk van de methoden die de gedelegeerde implementeert. Het kan ook worden aangepast om toegang te krijgen tot specifieke eigenschappen en om de contacten die het toont te filteren op basis van predicaten. Voor meer informatie, raad ik aan het lezen van de CNContactPickerViewController
klasseverwijzing en de CNContactPickerDelegate
protocolreferentie.
Zoals je ziet is het nieuwe raamwerk voor contactpersonen in iOS 9, OS X El Capitan en watchOS 2 een zeer goed ontworpen en gemakkelijk te gebruiken verzameling API's. U moet nu vertrouwd zijn met het openen, maken en bijwerken van contacten op het apparaat van een gebruiker. Laat zoals altijd uw opmerkingen en feedback achter in de opmerkingen hieronder.