Partager via


Contacts et CONTACTSUI dans Xamarin.iOS

Cet article traite de l’utilisation des nouveaux frameworks d’interface utilisateur Contacts et Contacts dans une application Xamarin.iOS. Ces frameworks remplacent l’interface utilisateur existante du carnet d’adresses et du carnet d’adresses utilisé dans les versions précédentes d’iOS.

Avec l’introduction d’iOS 9, Apple a publié deux nouvelles infrastructures et ContactsContactsUI, qui remplacent les frameworks existants de carnet d’adresses et d’interface utilisateur de carnet d’adresses utilisés par iOS 8 et versions antérieures.

Les deux nouvelles infrastructures contiennent les fonctionnalités suivantes :

  • Contacts : fournit l’accès aux données de la liste de contacts de l’utilisateur. Étant donné que la plupart des applications nécessitent uniquement un accès en lecture seule, cette infrastructure a été optimisée pour l’accès thread sécurisé et en lecture seule.

  • ContactsUI : fournit des éléments d’interface utilisateur Xamarin.iOS pour afficher, modifier, sélectionner et créer des contacts sur des appareils iOS.

Exemple de feuille de contact sur un appareil iOS

Important

Les infrastructures existantes AddressBook et AddressBookUI utilisées par iOS 8 (et antérieures) ont été déconseillées dans iOS 9 et doivent être remplacées par les nouvelles Contacts infrastructures ContactsUI dès que possible pour n’importe quelle application Xamarin.iOS existante. Les nouvelles applications doivent être écrites sur les nouvelles infrastructures.

Dans les sections suivantes, nous allons examiner ces nouvelles infrastructures et comment les implémenter dans une application Xamarin.iOS.

Infrastructure de contacts

L’infrastructure contacts fournit un accès Xamarin.iOS aux informations de contact de l’utilisateur. Étant donné que la plupart des applications nécessitent uniquement un accès en lecture seule, cette infrastructure a été optimisée pour l’accès thread sécurisé et en lecture seule.

Objets contact

La CNContact classe fournit un accès thread sécurisé et en lecture seule aux propriétés d’un contact, telles que Name, Address ou Téléphone Numbers. CNContact fonctionne comme un NSDictionary et contient plusieurs collections de propriétés en lecture seule (telles que des adresses ou des numéros de téléphone) :

Vue d’ensemble de l’objet Contact

Pour toutes les propriétés qui peuvent avoir plusieurs valeurs (telles que l’adresse e-mail ou les numéros de téléphone), elles sont représentées sous la forme d’un tableau d’objets NSLabeledValue . NSLabeledValue est un tuple sécurisé thread composé d’un ensemble d’étiquettes et de valeurs en lecture seule où l’étiquette définit la valeur à l’utilisateur (par exemple, e-mail accueil ou professionnel). L’infrastructure Contacts fournit une sélection d’étiquettes prédéfinies (via les CNLabelKey classes statiques) CNLabelPhoneNumberKey que vous pouvez utiliser dans votre application ou vous avez la possibilité de définir des étiquettes personnalisées pour vos besoins.

Pour toute application Xamarin.iOS qui doit ajuster les valeurs d’un contact existant (ou en créer de nouvelles), utilisez la NSMutableContact version de la classe et ses sous-classes (par exemple CNMutablePostalAddress).

Par exemple, le code suivant crée un contact et l’ajoute à la collection de contacts de l’utilisateur :

// Create a new Mutable Contact (read/write)
var contact = new CNMutableContact();

// Set standard properties
contact.GivenName = "John";
contact.FamilyName = "Appleseed";

// Add email addresses
var homeEmail = new CNLabeledValue<NSString>(CNLabelKey.Home, new NSString("john.appleseed@mac.com"));
var workEmail = new CNLabeledValue<NSString>(CNLabelKey.Work, new NSString("john.appleseed@apple.com"));
contact.EmailAddresses = new CNLabeledValue<NSString>[] { homeEmail, workEmail };

// Add phone numbers
var cellPhone = new CNLabeledValue<CNPhoneNumber>(CNLabelPhoneNumberKey.iPhone, new CNPhoneNumber("713-555-1212"));
var workPhone = new CNLabeledValue<CNPhoneNumber>("Work", new CNPhoneNumber("408-555-1212"));
contact.PhoneNumbers = new CNLabeledValue<CNPhoneNumber>[] { cellPhone, workPhone };

// Add work address
var workAddress = new CNMutablePostalAddress()
{
    Street = "1 Infinite Loop",
    City = "Cupertino",
    State = "CA",
    PostalCode = "95014"
};
contact.PostalAddresses = new CNLabeledValue<CNPostalAddress>[] { new CNLabeledValue<CNPostalAddress>(CNLabelKey.Work, workAddress) };

// Add birthday
var birthday = new NSDateComponents()
{
    Day = 1,
    Month = 4,
    Year = 1984
};
contact.Birthday = birthday;

// Save new contact
var store = new CNContactStore();
var saveRequest = new CNSaveRequest();
saveRequest.AddContact(contact, store.DefaultContainerIdentifier);

// Attempt to save changes
NSError error;
if (store.ExecuteSaveRequest(saveRequest, out error))
{
    Console.WriteLine("New contact saved");
}
else
{
    Console.WriteLine("Save error: {0}", error);
}

Si ce code est exécuté sur un appareil iOS 9, un nouveau contact est ajouté à la collection de l’utilisateur. Par exemple :

Un nouveau contact ajouté à la collection de l’utilisateur

Mise en forme et localisation des contacts

L’infrastructure Contacts contient plusieurs objets et méthodes qui peuvent vous aider à mettre en forme et localiser du contenu pour l’affichage à l’utilisateur. Par exemple, le code suivant formate correctement un nom de contacts et une adresse de publipostage pour l’affichage :

Console.WriteLine(CNContactFormatter.GetStringFrom(contact, CNContactFormatterStyle.FullName));
Console.WriteLine(CNPostalAddressFormatter.GetStringFrom(workAddress, CNPostalAddressFormatterStyle.MailingAddress));

Pour les étiquettes de propriétés que vous allez afficher dans l’interface utilisateur de votre application, l’infrastructure Contact a également des méthodes pour localiser ces chaînes. Là encore, cela est basé sur les paramètres régionaux actuels de l’appareil iOS sur lequel l’application est exécutée. Par exemple :

// Localized properties
Console.WriteLine(CNContact.LocalizeProperty(CNContactOptions.Nickname));
Console.WriteLine(CNLabeledValue<NSString>.LocalizeLabel(CNLabelKey.Home));

Extraction de contacts existants

À l’aide d’une instance de la CNContactStore classe, vous pouvez extraire les informations de contact de la base de données de contacts de l’utilisateur. Contient CNContactStore toutes les méthodes requises pour extraire ou mettre à jour des contacts et des groupes à partir de la base de données. Étant donné que ces méthodes sont synchrones, il est recommandé de les exécuter sur un thread d’arrière-plan pour empêcher l’interface utilisateur de bloquer.

En utilisant des prédicats (générés à partir de la CNContact classe), vous pouvez filtrer les résultats retournés lors de l’extraction de contacts à partir de la base de données. Pour extraire uniquement les contacts qui contiennent la chaîne Appleseed, utilisez le code suivant :

// Create predicate to locate requested contact
var predicate = CNContact.GetPredicateForContacts("Appleseed");

Important

Les prédicats génériques et composés ne sont pas pris en charge par l’infrastructure Contacts.

Par exemple, pour limiter la récupération uniquement aux propriétés GivenName et FamilyName du contact, utilisez le code suivant :

// Define fields to be searched
var fetchKeys = new NSString[] {CNContactKey.GivenName, CNContactKey.FamilyName};

Enfin, pour rechercher dans la base de données et retourner les résultats, utilisez le code suivant :

// Grab matching contacts
var store = new CNContactStore();
NSError error;
var contacts = store.GetUnifiedContacts(predicate, fetchKeys, out error);

Si ce code a été exécuté après l’exemple que nous avons créé dans la section Contacts Object ci-dessus, il renvoie le contact « John Appleseed » que nous venons de créer.

Confidentialité de l’accès aux contacts

Étant donné que les utilisateurs finaux peuvent accorder ou refuser l’accès à leurs informations de contact par application, la première fois que vous effectuez un appel à l’application CNContactStore, une boîte de dialogue leur demande d’autoriser l’accès à votre application.

La demande d’autorisation ne sera présentée qu’une seule fois, la première fois que l’application est exécutée, et les exécutions ou appels suivants à l’utilisateur CNContactStore utilisent l’autorisation sélectionnée à ce moment-là.

Vous devez concevoir votre application afin qu’elle gère correctement l’utilisateur qui refuse l’accès à sa base de données de contact.

Extraction de contacts partiels

Un contact partiel est un contact pour lequel seules certaines propriétés disponibles ont été extraites du magasin de contacts. Si vous essayez d’accéder à une propriété qui n’a pas été récupérée précédemment, elle entraîne une exception.

Vous pouvez facilement case activée pour voir si un contact donné a la propriété souhaitée à l’aide des méthodes ou AreKeysAvailable des IsKeyAvailable méthodes de l’instanceCNContact. Par exemple :

// Does the contact contain the requested key?
if (!contact.IsKeyAvailable(CNContactOption.PostalAddresses)) {
    // No, re-request to pull required info
    var fetchKeys = new NSString[] {CNContactKey.GivenName, CNContactKey.FamilyName, CNContactKey.PostalAddresses};
    var store = new CNContactStore();
    NSError error;
    contact = store.GetUnifiedContact(contact.Identifier, fetchKeys, out error);
}

Important

Les GetUnifiedContact méthodes de GetUnifiedContacts la CNContactStore classe retournent uniquement un contact partiel limité aux propriétés demandées à partir des clés d’extraction fournies.

Contacts unifiés

Un utilisateur peut avoir différentes sources d’informations de contact pour une seule personne dans sa base de données de contacts (comme iCloud, Facebook ou Google Mail). Dans les applications iOS et OS X, ces informations de contact sont automatiquement liées et affichées à l’utilisateur en tant que contact unifié unique :

Vue d’ensemble des contacts unifiés

Ce contact unifié est une vue temporaire en mémoire des informations de contact du lien qui recevront son propre identificateur unique (qui doit être utilisé pour réfuter le contact si nécessaire). Par défaut, l’infrastructure Contacts retourne un contact unifié dans la mesure du possible.

Création et mise à jour de contacts

Comme nous l’avons vu dans la section Objets de contact ci-dessus, vous utilisez une instance et une CNContactStore instance d’un CNMutableContact pour créer de nouveaux contacts qui sont ensuite écrits dans la base de données de contacts de l’utilisateur à l’aide d’un CNSaveRequest:

// Create a new Mutable Contact (read/write)
var contact = new CNMutableContact();

// Set standard properties
contact.GivenName = "John";
contact.FamilyName = "Appleseed";

// Save new contact
var store = new CNContactStore();
var saveRequest = new CNSaveRequest();
saveRequest.AddContact(contact, store.DefaultContainerIdentifier);

NSError error;
if (store.ExecuteSaveRequest(saveRequest, out error)) {
    Console.WriteLine("New contact saved");
} else {
    Console.WriteLine("Save error: {0}", error);
}

Un CNSaveRequest peut également être utilisé pour mettre en cache plusieurs modifications de contact et de groupe en une seule opération et traiter ces modifications dans le CNContactStore.

Pour mettre à jour un contact non mutable obtenu à partir d’une opération de récupération, vous devez d’abord demander une copie mutable que vous modifiez et enregistrez dans le magasin de contacts. Par exemple :

// Get mutable copy of contact
var mutable = contact.MutableCopy() as CNMutableContact;
var newEmail = new CNLabeledValue<NSString>(CNLabelKey.Home, new NSString("john.appleseed@xamarin.com"));

// Append new email
var emails = new NSObject[mutable.EmailAddresses.Length+1];
mutable.EmailAddresses.CopyTo(emails,0);
emails[mutable.EmailAddresses.Length+1] = newEmail;
mutable.EmailAddresses = emails;

// Update contact
var store = new CNContactStore();
var saveRequest = new CNSaveRequest();
saveRequest.UpdateContact(mutable);

NSError error;
if (store.ExecuteSaveRequest(saveRequest, out error)) {
    Console.WriteLine("Contact updated.");
} else {
    Console.WriteLine("Update error: {0}", error);
}

Notifications de modification de contact

Chaque fois qu’un contact est modifié, le Magasin de contacts publie un CNContactStoreDidChangeNotification message dans le Centre de notification par défaut. Si vous avez mis en cache ou que vous affichez actuellement des contacts, vous devez actualiser ces objets à partir du Magasin de contacts (CNContactStore).

Conteneurs et groupes

Les contacts d’un utilisateur peuvent exister localement sur l’appareil de l’utilisateur ou en tant que contacts synchronisés avec l’appareil à partir d’un ou plusieurs comptes de serveur (comme Facebook ou Google). Chaque pool de contacts possède son propre conteneur et un contact donné ne peut exister qu’dans un seul conteneur.

Vue d’ensemble des conteneurs et des groupes

Certains conteneurs permettent aux contacts d’être organisés en un ou plusieurs groupes ou sous-groupes. Ce comportement dépend du magasin de stockage d’un conteneur donné. Par exemple, iCloud n’a qu’un seul conteneur, mais peut avoir de nombreux groupes (mais pas de sous-groupes). Microsoft Exchange ne prend pas en charge les groupes, mais peut avoir plusieurs conteneurs (un pour chaque dossier Exchange).

Chevauchement dans les conteneurs et les groupes

Infrastructure ContactsUI

Dans les cas où votre application n’a pas besoin de présenter une interface utilisateur personnalisée, vous pouvez utiliser l’infrastructure ContactsUI pour présenter des éléments d’interface utilisateur pour afficher, modifier, sélectionner et créer des contacts dans votre application Xamarin.iOS.

En utilisant les contrôles intégrés d’Apple, vous réduisez non seulement la quantité de code que vous devez créer pour prendre en charge les contacts dans votre application Xamarin.iOS, mais vous présentez une interface cohérente aux utilisateurs de l’application.

Contrôleur de vue sélecteur de contacts

Le contrôleur de vue sélecteur de contacts (CNContactPickerViewController) gère la vue sélecteur de contacts standard qui permet à l’utilisateur de sélectionner un contact ou une propriété Contact dans la base de données de contact de l’utilisateur. L’utilisateur peut sélectionner un ou plusieurs contacts (en fonction de son utilisation) et le contrôleur de vue sélecteur de contacts n’invite pas à obtenir l’autorisation avant d’afficher le sélecteur.

Avant d’appeler la CNContactPickerViewController classe, vous définissez les propriétés que l’utilisateur peut sélectionner et définir des prédicats pour contrôler l’affichage et la sélection des propriétés du contact.

Utilisez une instance de la classe qui hérite de CNContactPickerDelegate répondre à l’interaction de l’utilisateur avec le sélecteur. Par exemple :

using System;
using System.Linq;
using UIKit;
using Foundation;
using Contacts;
using ContactsUI;

namespace iOS9Contacts
{
    public class ContactPickerDelegate: CNContactPickerDelegate
    {
        #region Constructors
        public ContactPickerDelegate ()
        {
        }

        public ContactPickerDelegate (IntPtr handle) : base (handle)
        {
        }
        #endregion

        #region Override Methods
        public override void ContactPickerDidCancel (CNContactPickerViewController picker)
        {
            Console.WriteLine ("User canceled picker");

        }

        public override void DidSelectContact (CNContactPickerViewController picker, CNContact contact)
        {
            Console.WriteLine ("Selected: {0}", contact);
        }

        public override void DidSelectContactProperty (CNContactPickerViewController picker, CNContactProperty contactProperty)
        {
            Console.WriteLine ("Selected Property: {0}", contactProperty);
        }
        #endregion
    }
}

Pour permettre à l’utilisateur de sélectionner une adresse e-mail à partir des contacts de sa base de données, vous pouvez utiliser le code suivant :

// Create a new picker
var picker = new CNContactPickerViewController();

// Select property to pick
picker.DisplayedPropertyKeys = new NSString[] {CNContactKey.EmailAddresses};
picker.PredicateForEnablingContact = NSPredicate.FromFormat("emailAddresses.@count > 0");
picker.PredicateForSelectionOfContact = NSPredicate.FromFormat("emailAddresses.@count == 1");

// Respond to selection
picker.Delegate = new ContactPickerDelegate();

// Display picker
PresentViewController(picker,true,null);

Contrôleur d’affichage du contact

La classe Contact View Controller (CNContactViewController) fournit un contrôleur pour présenter une vue contact standard à l’utilisateur final. L’affichage Contact peut afficher de nouveaux contacts nouveaux, inconnus ou existants et le type doit être spécifié avant l’affichage en appelant le constructeur statique approprié (FromNewContact, FromUnknownContact, FromContact). Par exemple :

// Create a new contact view
var view = CNContactViewController.FromContact(contact);

// Display the view
PresentViewController(view, true, null);

Résumé

Cet article a examiné en détail l’utilisation des frameworks d’interface utilisateur contact et contact dans une application Xamarin.iOS. Tout d’abord, il a abordé les différents types d’objets que l’infrastructure Contact fournit et comment vous les utilisez pour créer des contacts existants ou y accéder. Il a également examiné l’infrastructure de l’interface utilisateur de contact pour sélectionner les contacts existants et afficher les informations de contact.