Kontakte und KontakteUI in Xamarin.iOS
In diesem Artikel wird die Arbeit mit den neuen Benutzeroberflächenframeworks für Kontakte und Kontakte in einer Xamarin.iOS-App behandelt. Diese Frameworks ersetzen die vorhandene Benutzeroberfläche für Adressbuch und Adressbuch, die in früheren Versionen von iOS verwendet wurden.
Mit der Einführung von iOS 9 hat Apple zwei neue Frameworks und ContactsUI
veröffentlicht, Contacts
die die vorhandenen Frameworks für adressbuch- und adressbuchbenutzeroberfläche ersetzen, die von iOS 8 und früher verwendet werden.
Die beiden neuen Frameworks enthalten die folgenden Funktionen:
Kontakte : Bietet Zugriff auf die Kontaktlistendaten des Benutzers. Da die meisten Apps nur schreibgeschützten Zugriff erfordern, wurde dieses Framework für threadsicheren, schreibgeschützten Zugriff optimiert.
ContactsUI : Stellt Xamarin.iOS-Ui-Elemente zum Anzeigen, Bearbeiten, Auswählen und Erstellen von Kontakten auf iOS-Geräten bereit.
Wichtig
Die vorhandenen AddressBook
Frameworks und AddressBookUI
, die von iOS 8 (und früher) verwendet werden, sind in iOS 9 veraltet und sollten so bald wie möglich für jede vorhandene Xamarin.iOS-App durch die neuen Contacts
Frameworks und ContactsUI
ersetzt werden. Neue Apps sollten für die neuen Frameworks geschrieben werden.
In den folgenden Abschnitten sehen wir uns diese neuen Frameworks an und erfahren, wie Sie sie in einer Xamarin.iOS-App implementieren.
Das Kontakte-Framework
Das Contacts Framework bietet Xamarin.iOS-Zugriff auf die Kontaktinformationen des Benutzers. Da die meisten Apps nur schreibgeschützten Zugriff erfordern, wurde dieses Framework für threadsicheren, schreibgeschützten Zugriff optimiert.
Kontaktobjekte
Die CNContact
-Klasse bietet threadsicheren, schreibgeschützten Zugriff auf die Eigenschaften eines Kontakts wie Name, Adresse oder Telefonnummern. CNContact
Funktionen wie und NSDictionary
enthält mehrere schreibgeschützte Auflistungen von Eigenschaften (z. B. Adressen oder Telefonnummern):
Für jede Eigenschaft, die mehrere Werte aufweisen kann (z. B. E-Mail-Adresse oder Telefonnummern), werden sie als Array von NSLabeledValue
Objekten dargestellt. NSLabeledValue
ist ein threadsicheres Tupel, das aus einem schreibgeschützten Satz von Bezeichnungen und Werten besteht, bei dem die Bezeichnung den Wert für den Benutzer definiert (z. B. Home- oder Work-E-Mail). Das Contacts-Framework bietet eine Auswahl vordefinierter Bezeichnungen (über die CNLabelKey
statischen Klassen und CNLabelPhoneNumberKey
), die Sie in Ihrer App verwenden können, oder Sie haben die Möglichkeit, benutzerdefinierte Bezeichnungen für Ihre Anforderungen zu definieren.
Verwenden Sie für jede Xamarin.iOS-App, die die Werte eines vorhandenen Kontakts anpassen (oder neue erstellen muss), die NSMutableContact
Version der -Klasse und deren Unterklassen (z CNMutablePostalAddress
. B. ).
Mit dem folgenden Code wird beispielsweise ein neuer Kontakt erstellt und der Kontaktsammlung des Benutzers hinzugefügt:
// 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);
}
Wenn dieser Code auf einem iOS 9-Gerät ausgeführt wird, wird der Sammlung des Benutzers ein neuer Kontakt hinzugefügt. Beispiel:
Kontaktformatierung und Lokalisierung
Das Contacts-Framework enthält mehrere Objekte und Methoden, mit denen Sie Inhalte für die Anzeige für den Benutzer formatieren und lokalisieren können. Der folgende Code würde beispielsweise einen Kontaktnamen und eine Postanschrift für die Anzeige korrekt formatieren:
Console.WriteLine(CNContactFormatter.GetStringFrom(contact, CNContactFormatterStyle.FullName));
Console.WriteLine(CNPostalAddressFormatter.GetStringFrom(workAddress, CNPostalAddressFormatterStyle.MailingAddress));
Für Eigenschaftenbezeichnungen, die Sie auf der Benutzeroberfläche Ihrer App anzeigen, verfügt das Contact-Framework auch über Methoden zum Lokalisieren dieser Zeichenfolgen. Auch dies basiert auf dem aktuellen Gebietsschema des iOS-Geräts, auf dem die App ausgeführt wird. Beispiel:
// Localized properties
Console.WriteLine(CNContact.LocalizeProperty(CNContactOptions.Nickname));
Console.WriteLine(CNLabeledValue<NSString>.LocalizeLabel(CNLabelKey.Home));
Abrufen vorhandener Kontakte
Mithilfe einer instance der CNContactStore
-Klasse können Sie Kontaktinformationen aus der Kontaktdatenbank des Benutzers abrufen. Enthält CNContactStore
alle Methoden, die zum Abrufen oder Aktualisieren von Kontakten und Gruppen aus der Datenbank erforderlich sind. Da diese Methoden synchron sind, wird empfohlen, sie in einem Hintergrundthread auszuführen, damit die Benutzeroberfläche nicht blockiert wird.
Mithilfe von Prädikaten (aus der CNContact
-Klasse erstellt) können Sie die Ergebnisse filtern, die beim Abrufen von Kontakten aus der Datenbank zurückgegeben werden. Verwenden Sie den folgenden Code, um nur Kontakte abzurufen, die die Zeichenfolge Appleseed
enthalten:
// Create predicate to locate requested contact
var predicate = CNContact.GetPredicateForContacts("Appleseed");
Wichtig
Generische prädikate und zusammengesetzte Prädikate werden vom Contacts-Framework nicht unterstützt.
Verwenden Sie beispielsweise den folgenden Code, um den Abruf nur auf die Eigenschaften GivenName und FamilyName des Kontakts zu beschränken:
// Define fields to be searched
var fetchKeys = new NSString[] {CNContactKey.GivenName, CNContactKey.FamilyName};
Verwenden Sie schließlich den folgenden Code, um die Datenbank zu durchsuchen und die Ergebnisse zurückzugeben:
// Grab matching contacts
var store = new CNContactStore();
NSError error;
var contacts = store.GetUnifiedContacts(predicate, fetchKeys, out error);
Wenn dieser Code nach dem Beispiel ausgeführt wird, das wir oben im Abschnitt Contacts-Objekt erstellt haben, würde er den soeben erstellten Kontakt "John Appleseed" zurückgeben.
Kontakt Zum Datenschutz
Da Endbenutzer den Zugriff auf ihre Kontaktinformationen pro Anwendung gewähren oder verweigern können, wird beim ersten Aufruf von bei ein Dialogfeld angezeigt, in dem CNContactStore
sie aufgefordert werden, den Zugriff auf Ihre App zuzulassen.
Die Berechtigungsanforderung wird nur einmal angezeigt, wenn die App zum ersten Mal ausgeführt wird, und nachfolgende Ausführungen oder Aufrufe von CNContactStore
verwenden die Berechtigung, die der Benutzer zu diesem Zeitpunkt ausgewählt hat.
Sie sollten Ihre App so entwerfen, dass sie den Benutzer ordnungsgemäß behandelt, der den Zugriff auf seine Kontaktdatenbank verweigert.
Abrufen von Teilkontakten
Ein Partieller Kontakt ist ein Kontakt, für den nur einige der verfügbaren Eigenschaften aus dem Kontaktspeicher abgerufen wurden. Wenn Sie versuchen, auf eine Eigenschaft zuzugreifen, die zuvor nicht abgerufen wurde, führt dies zu einer Ausnahme.
Sie können leicht überprüfen, ob ein gegebener Kontakt über die gewünschte Eigenschaft verfügt, indem Sie entweder die -Methode oder AreKeysAvailable
die IsKeyAvailable
-Methode des CNContact
instance verwenden. Beispiel:
// 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);
}
Wichtig
Die GetUnifiedContact
Methoden und GetUnifiedContacts
der CNContactStore
-Klasse geben nur einen Partiellen Kontakt zurück, der auf die Eigenschaften beschränkt ist, die von den bereitgestellten Abrufschlüsseln angefordert werden.
Vereinheitlichte Kontakte
Ein Benutzer verfügt möglicherweise über verschiedene Quellen von Kontaktinformationen für eine einzelne Person in seiner Kontaktdatenbank (z. B. iCloud, Facebook oder Google Mail). In iOS- und OS X-Apps werden diese Kontaktinformationen automatisch miteinander verknüpft und dem Benutzer als einheitlicher Kontakt angezeigt:
Bei diesem einheitlichen Kontakt handelt es sich um eine temporäre In-Memory-Ansicht der Linkkontaktinformationen, die einen eigenen eindeutigen Bezeichner erhalten (der bei Bedarf zum Refetch des Kontakts verwendet werden sollte). Standardmäßig gibt das Kontakteframework nach Möglichkeit einen einheitlichen Kontakt zurück.
Erstellen und Aktualisieren von Kontakten
Wie wir oben im Abschnitt Kontaktobjekte gesehen haben, verwenden Sie eine CNContactStore
und eine instance von , CNMutableContact
um neue Kontakte zu erstellen, die dann mithilfe von in CNSaveRequest
die Kontaktdatenbank des Benutzers geschrieben werden:
// 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);
}
Ein CNSaveRequest
kann auch verwendet werden, um mehrere Kontakt- und Gruppierungsänderungen in einem einzelnen Vorgang zwischenzuspeichern und diese Änderungen in batch zu batchen CNContactStore
.
Um einen nicht veränderlichen Kontakt zu aktualisieren, der aus einem Abrufvorgang abgerufen wurde, müssen Sie zunächst eine veränderliche Kopie anfordern, die Sie dann ändern und wieder im Kontaktspeicher speichern. Beispiel:
// 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);
}
Kontaktänderungsbenachrichtigungen
Wenn ein Kontakt geändert wird, stellt der Kontaktspeicher eine CNContactStoreDidChangeNotification
im Standardbenachrichtigungscenter bereit. Wenn Sie Kontakte zwischengespeichert haben oder gerade anzeigen, müssen Sie diese Objekte aus dem Kontaktspeicher (CNContactStore
) aktualisieren.
Container und Gruppen
Die Kontakte eines Benutzers können entweder lokal auf dem Gerät des Benutzers oder als Kontakte vorhanden sein, die von einem oder mehreren Serverkonten (z. B. Facebook oder Google) mit dem Gerät synchronisiert werden. Jeder Kontaktpool verfügt über einen eigenen Container , und ein bestimmter Kontakt kann nur in einem Container vorhanden sein.
In einigen Containern können Kontakte in eine oder mehrere Gruppen oder Untergruppen angeordnet werden. Dieses Verhalten hängt vom Sicherungsspeicher für einen bestimmten Container ab. Beispielsweise verfügt iCloud nur über einen Container, kann jedoch viele Gruppen (aber keine Untergruppen) haben. Microsoft Exchange hingegen unterstützt keine Gruppen, kann aber mehrere Container (einen für jeden Exchange-Ordner) haben.
Das ContactsUI-Framework
In Situationen, in denen Ihre Anwendung keine benutzerdefinierte Benutzeroberfläche präsentieren muss, können Sie das ContactsUI-Framework verwenden, um UI-Elemente zum Anzeigen, Bearbeiten, Auswählen und Erstellen von Kontakten in Ihrer Xamarin.iOS-App anzuzeigen, zu bearbeiten, auszuwählen und zu erstellen.
Durch die Verwendung der integrierten Apple-Steuerelemente reduzieren Sie nicht nur die Menge an Code, die Sie erstellen müssen, um Kontakte in Ihrer Xamarin.iOS-App zu unterstützen, sondern stellen auch eine konsistente Oberfläche für die Benutzer der App bereit.
Der Ansichtscontroller für die Kontaktauswahl
Der Ansichtscontroller für die Kontaktauswahl (CNContactPickerViewController
) verwaltet die Standardmäßige Kontaktauswahlansicht, mit der der Benutzer einen Kontakt oder eine Kontakteigenschaft aus der Kontaktdatenbank des Benutzers auswählen kann. Der Benutzer kann einen oder mehrere Kontakt (basierend auf seiner Verwendung) auswählen, und der Ansichtscontroller für die Kontaktauswahl fordert vor dem Anzeigen der Auswahl nicht zur Berechtigung auf.
Bevor Sie die CNContactPickerViewController
-Klasse aufrufen, definieren Sie, welche Eigenschaften der Benutzer auswählen und Prädikate definieren kann, um die Anzeige und Auswahl von Kontakteigenschaften zu steuern.
Verwenden Sie eine instance der Klasse, die von CNContactPickerDelegate
erbt, um auf die Interaktion des Benutzers mit der Auswahl zu reagieren. Beispiel:
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
}
}
Damit der Benutzer eine E-Mail-Adresse aus den Kontakten in seiner Datenbank auswählen kann, können Sie den folgenden Code verwenden:
// 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);
Der Kontaktansichtscontroller
Die Contact View Controller -Klasse (CNContactViewController
) stellt einen Controller bereit, um dem Endbenutzer eine Standardkontaktansicht zu präsentieren. In der Kontaktansicht können neue, unbekannte oder vorhandene Kontakte angezeigt werden, und der Typ muss angegeben werden, bevor die Ansicht durch Aufrufen des richtigen statischen Konstruktors (FromNewContact
, FromUnknownContact
, FromContact
) angezeigt wird. Beispiel:
// Create a new contact view
var view = CNContactViewController.FromContact(contact);
// Display the view
PresentViewController(view, true, null);
Zusammenfassung
In diesem Artikel wird die Arbeit mit den Benutzeroberflächenframeworks "Kontakt" und "Kontakt" in einer Xamarin.iOS-Anwendung ausführlich erläutert. Zunächst wurden die verschiedenen Arten von Objekten behandelt, die das Contact-Framework bereitstellt, und wie Sie sie verwenden, um neue Kontakte zu erstellen oder auf vorhandene Kontakte zuzugreifen. Außerdem wurde das Framework für die Kontaktbenutzeroberfläche untersucht, um vorhandene Kontakte auszuwählen und Kontaktinformationen anzuzeigen.