Contatti e contattiUI in Xamarin.iOS
Questo articolo illustra l'uso dei nuovi framework dell'interfaccia utente Contatti e Contatti in un'app Xamarin.iOS. Questi framework sostituiscono l'interfaccia utente della Rubrica e della Rubrica esistente usata nelle versioni precedenti di iOS.
Con l'introduzione di iOS 9, Apple ha rilasciato due nuovi framework, Contacts
e ContactsUI
, che sostituiscono i framework esistenti dell'interfaccia utente rubrica e rubrica usati da iOS 8 e versioni precedenti.
I due nuovi framework contengono le funzionalità seguenti:
Contatti : consente di accedere ai dati dell'elenco contatti dell'utente. Poiché la maggior parte delle app richiede solo l'accesso in sola lettura, questo framework è stato ottimizzato per l'accesso thread-safe e di sola lettura.
ContactsUI : fornisce elementi dell'interfaccia utente Xamarin.iOS per visualizzare, modificare, selezionare e creare contatti nei dispositivi iOS.
Importante
I framework e AddressBookUI
esistenti AddressBook
usati da iOS 8 (e versioni precedenti) sono stati deprecati in iOS 9 e devono essere sostituiti con i nuovi Contacts
framework e ContactsUI
appena possibile per qualsiasi app Xamarin.iOS esistente. Le nuove app devono essere scritte nei nuovi framework.
Nelle sezioni seguenti verranno esaminati questi nuovi framework e come implementarli in un'app Xamarin.iOS.
Framework contatti
Contacts Framework fornisce a Xamarin.iOS l'accesso alle informazioni di contatto dell'utente. Poiché la maggior parte delle app richiede solo l'accesso in sola lettura, questo framework è stato ottimizzato per l'accesso thread-safe e di sola lettura.
Oggetti contatto
La CNContact
classe fornisce accesso thread-safe e di sola lettura alle proprietà di un contatto, ad esempio Name, Address o Telefono Numbers. CNContact
funzioni come e NSDictionary
contiene più raccolte di proprietà di sola lettura , ad esempio indirizzi o numeri di telefono:
Per qualsiasi proprietà che può avere più valori, ad esempio l'indirizzo di posta elettronica o i numeri di telefono, verranno rappresentati come una matrice di NSLabeledValue
oggetti. NSLabeledValue
è una tupla thread-safe costituita da un set di etichette e valori di sola lettura in cui l'etichetta definisce il valore per l'utente (ad esempio, indirizzo di posta elettronica home o aziendale). Il framework Contatti offre una selezione di etichette predefinite (tramite le CNLabelKey
classi statiche e CNLabelPhoneNumberKey
) che è possibile usare nell'app oppure è possibile definire etichette personalizzate per le proprie esigenze.
Per qualsiasi app Xamarin.iOS che deve modificare i valori di un contatto esistente (o crearne di nuovi), usare la NSMutableContact
versione della classe e le relative classi secondarie ( ad esempio CNMutablePostalAddress
).
Ad esempio, il codice seguente creerà un nuovo contatto e lo aggiungerà alla raccolta di contatti dell'utente:
// 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);
}
Se questo codice viene eseguito in un dispositivo iOS 9, alla raccolta dell'utente verrà aggiunto un nuovo contatto. Ad esempio:
Formattazione e localizzazione dei contatti
Il framework Contacts contiene diversi oggetti e metodi che consentono di formattare e localizzare il contenuto per la visualizzazione all'utente. Ad esempio, il codice seguente formatta correttamente un nome di contatti e un indirizzo postale per la visualizzazione:
Console.WriteLine(CNContactFormatter.GetStringFrom(contact, CNContactFormatterStyle.FullName));
Console.WriteLine(CNPostalAddressFormatter.GetStringFrom(workAddress, CNPostalAddressFormatterStyle.MailingAddress));
Per le etichette delle proprietà che verranno visualizzate nell'interfaccia utente dell'app, il framework contact include anche metodi per localizzare tali stringhe. Anche in questo caso, si basa sulle impostazioni locali correnti del dispositivo iOS in cui viene eseguita l'app. Ad esempio:
// Localized properties
Console.WriteLine(CNContact.LocalizeProperty(CNContactOptions.Nickname));
Console.WriteLine(CNLabeledValue<NSString>.LocalizeLabel(CNLabelKey.Home));
Recupero di contatti esistenti
Usando un'istanza della CNContactStore
classe , è possibile recuperare le informazioni di contatto dal database contatti dell'utente. CNContactStore
Contiene tutti i metodi necessari per il recupero o l'aggiornamento di contatti e gruppi dal database. Poiché questi metodi sono sincroni, è consigliabile eseguirli in un thread in background per evitare di bloccare l'interfaccia utente.
Usando predicati (compilati dalla CNContact
classe ), è possibile filtrare i risultati restituiti durante il recupero dei contatti dal database. Per recuperare solo i contatti che contengono la stringa Appleseed
, usare il codice seguente:
// Create predicate to locate requested contact
var predicate = CNContact.GetPredicateForContacts("Appleseed");
Importante
I predicati generici e composti non sono supportati dal framework Contatti.
Ad esempio, per limitare il recupero solo alle proprietà GivenName e FamilyName del contatto, usare il codice seguente:
// Define fields to be searched
var fetchKeys = new NSString[] {CNContactKey.GivenName, CNContactKey.FamilyName};
Infine, per eseguire una ricerca nel database e restituire i risultati, usare il codice seguente:
// Grab matching contacts
var store = new CNContactStore();
NSError error;
var contacts = store.GetUnifiedContacts(predicate, fetchKeys, out error);
Se questo codice è stato eseguito dopo l'esempio creato nella sezione Oggetto Contatti precedente, restituirà il contatto "John Appleseed" appena creato.
Privacy dell'accesso ai contatti
Poiché gli utenti finali possono concedere o negare l'accesso alle informazioni di contatto in base all'applicazione, la prima volta che si effettua una chiamata a , verrà visualizzata una finestra di dialogo che chiede di consentire l'accesso per l'app CNContactStore
.
La richiesta di autorizzazione verrà presentata una sola volta, la prima volta che l'app viene eseguita e le successive esecuzioni o chiamate a CNContactStore
useranno l'autorizzazione selezionata dall'utente in quel momento.
È consigliabile progettare l'app in modo che gestisca normalmente l'utente negando l'accesso al database dei contatti.
Recupero di contatti parziali
Un contatto parziale è un contatto per cui sono state recuperate solo alcune delle proprietà disponibili dall'archivio contatti. Se si tenta di accedere a una proprietà non recuperata in precedenza, verrà generata un'eccezione.
È possibile verificare facilmente se un determinato contatto ha la proprietà desiderata usando i IsKeyAvailable
metodi o AreKeysAvailable
dell'istanza CNContact
. Ad esempio:
// 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);
}
Importante
I GetUnifiedContact
metodi e GetUnifiedContacts
della CNContactStore
classe restituiscono solo un contatto parziale limitato alle proprietà richieste dalle chiavi di recupero fornite.
Contatti unificati
Un utente potrebbe avere diverse origini di informazioni di contatto per una singola persona nel database dei contatti (ad esempio iCloud, Facebook o Google Mail). Nelle app iOS e OS X queste informazioni di contatto verranno automaticamente collegate e visualizzate all'utente come singolo contatto unificato:
Questo contatto unificato è una visualizzazione temporanea in memoria delle informazioni di contatto di collegamento a cui verrà assegnato il proprio identificatore univoco (che deve essere usato per rifare il contatto, se necessario). Per impostazione predefinita, il framework Contatti restituirà un contatto unificato ogni volta che possibile.
Creazione e aggiornamento dei contatti
Come illustrato nella sezione Oggetti contatto precedente, si usa un CNContactStore
oggetto e un'istanza di per CNMutableContact
creare nuovi contatti che vengono quindi scritti nel database dei contatti dell'utente usando :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
oggetto può essere usato anche per memorizzare nella cache più modifiche di contatto e gruppo in un'unica operazione e raggruppare tali modifiche in CNContactStore
.
Per aggiornare un contatto non modificabile ottenuto da un'operazione di recupero, è prima necessario richiedere una copia modificabile che si modifica e si salva nell'archivio contatti. Ad esempio:
// 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);
}
Notifiche di modifica contatto
Ogni volta che un contatto viene modificato, l'archivio contatti invia un oggetto CNContactStoreDidChangeNotification
al Centro notifiche predefinito. Se sono stati memorizzati nella cache o sono attualmente visualizzati contatti, sarà necessario aggiornare tali oggetti dall'Archivio contatti (CNContactStore
).
Contenitori e gruppi
I contatti di un utente possono esistere localmente nel dispositivo dell'utente o come contatti sincronizzati con il dispositivo da uno o più account server (ad esempio Facebook o Google). Ogni pool di contatti ha un proprio contenitore e un determinato contatto può esistere solo in un contenitore.
Alcuni contenitori consentono di disporre i contatti in uno o più gruppi o sottogruppi. Questo comportamento dipende dall'archivio di backup per un determinato contenitore. Ad esempio, iCloud ha un solo contenitore, ma può avere molti gruppi (ma nessun sottogruppi). Microsoft Exchange, invece, non supporta i gruppi, ma può avere più contenitori (uno per ogni cartella di Exchange).
The ContactsUI Framework
Per le situazioni in cui l'applicazione non deve presentare un'interfaccia utente personalizzata, è possibile usare il framework ContactsUI per presentare gli elementi dell'interfaccia utente per visualizzare, modificare e creare contatti nell'app Xamarin.iOS.
Usando i controlli predefiniti di Apple non solo si riduce la quantità di codice che è necessario creare per supportare i contatti nell'app Xamarin.iOS, ma si presenta un'interfaccia coerente agli utenti dell'app.
Controller di visualizzazione selezione contatti
Il controller di visualizzazione selezione contatti (CNContactPickerViewController
) gestisce la visualizzazione standard selezione contatti che consente all'utente di selezionare un contatto o una proprietà Contact dal database contatti dell'utente. L'utente può selezionare uno o più contatti (in base all'utilizzo) e il controller di visualizzazione selezione contatto non richiede l'autorizzazione prima di visualizzare la selezione.
Prima di chiamare la CNContactPickerViewController
classe, definire le proprietà che l'utente può selezionare e definire predicati per controllare la visualizzazione e la selezione di Proprietà contatto.
Usare un'istanza della classe che eredita da CNContactPickerDelegate
per rispondere all'interazione dell'utente con la selezione. Ad esempio:
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
}
}
Per consentire all'utente di selezionare un indirizzo di posta elettronica dai contatti nel database, è possibile usare il codice seguente:
// 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);
Controller di visualizzazione contatto
La classe Contact View Controller (CNContactViewController
) fornisce un controller per presentare una visualizzazione contatto standard all'utente finale. La visualizzazione Contatto può visualizzare nuovi contatti Nuovi, Sconosciuti o Esistenti e il tipo deve essere specificato prima che la visualizzazione venga visualizzata chiamando il costruttore statico corretto (FromNewContact
, FromUnknownContact
, FromContact
). Ad esempio:
// Create a new contact view
var view = CNContactViewController.FromContact(contact);
// Display the view
PresentViewController(view, true, null);
Riepilogo
Questo articolo ha esaminato in dettaglio l'uso dei framework contatto e contatto dell'interfaccia utente in un'applicazione Xamarin.iOS. In primo luogo, sono stati illustrati i diversi tipi di oggetti forniti dal framework contact e come usarli per creare contatti nuovi o accedere a contatti esistenti. Ha anche esaminato il framework dell'interfaccia utente contatto per selezionare i contatti esistenti e visualizzare le informazioni di contatto.