Udostępnij za pośrednictwem


Kontakty i interfejs ContactsUI na platformie Xamarin.iOS

W tym artykule opisano pracę z nowymi strukturami interfejsu użytkownika Kontakty i kontakty w aplikacji platformy Xamarin.iOS. Te struktury zastępują istniejącą książkę adresową i interfejs użytkownika książki adresowej używany w poprzednich wersjach systemu iOS.

Wraz z wprowadzeniem systemu iOS 9 firma Apple wydała dwie nowe struktury i ContactsContactsUI, które zastępują istniejące struktury interfejsu użytkownika książki adresowej i książki adresowej używane przez system iOS 8 i starsze.

Dwie nowe struktury zawierają następujące funkcje:

  • Kontakty — zapewnia dostęp do danych listy kontaktów użytkownika. Ponieważ większość aplikacji wymaga tylko dostępu tylko do odczytu, ta struktura została zoptymalizowana pod kątem bezpiecznego wątkowego dostępu tylko do odczytu.

  • ContactsUI — udostępnia elementy interfejsu użytkownika platformy Xamarin.iOS do wyświetlania, edytowania, wybierania i tworzenia kontaktów na urządzeniach z systemem iOS.

Przykładowy arkusz kontaktowy na urządzeniu z systemem iOS

Ważne

Istniejące AddressBook platformy i AddressBookUI używane przez system iOS 8 (i wcześniejsze) zostały uznane za przestarzałe w systemie iOS 9 i powinny zostać zastąpione nowymi ContactsContactsUI strukturami tak szybko, jak to możliwe dla dowolnej istniejącej aplikacji platformy Xamarin.iOS. Nowe aplikacje powinny być zapisywane w nowych strukturach.

W poniższych sekcjach przyjrzymy się tym nowym strukturom i sposobom ich implementowania w aplikacji platformy Xamarin.iOS.

Struktura kontaktów

Platforma Kontaktów zapewnia dostęp platformy Xamarin.iOS do informacji kontaktowych użytkownika. Ponieważ większość aplikacji wymaga tylko dostępu tylko do odczytu, ta struktura została zoptymalizowana pod kątem bezpiecznego wątkowego dostępu tylko do odczytu.

Obiekty kontaktu

Klasa CNContact zapewnia bezpieczny wątkowo dostęp tylko do odczytu do właściwości kontaktu, takich jak Nazwa, Adres lub Numery Telefon. CNContact funkcje takie jak i NSDictionary zawierają wiele kolekcji właściwości tylko do odczytu (takich jak adresy lub numery telefonów):

Omówienie obiektu kontaktu

W przypadku każdej właściwości, która może mieć wiele wartości (takich jak adres e-mail lub numery telefonów), będą one reprezentowane jako tablica NSLabeledValue obiektów. NSLabeledValue to bezpieczna krotka wątkowa składająca się z zestawu etykiet i wartości tylko do odczytu, w których etykieta definiuje wartość użytkownikowi (na przykład wiadomość e-mail home lub work). Platforma Kontakty udostępnia wybór wstępnie zdefiniowanych etykiet (za pośrednictwem CNLabelKey klas statycznych i CNLabelPhoneNumberKey ), których można używać w aplikacji lub istnieje możliwość definiowania etykiet niestandardowych dla Twoich potrzeb.

W przypadku dowolnej aplikacji platformy Xamarin.iOS, która musi dostosować wartości istniejącego kontaktu (lub utworzyć nowe), użyj NSMutableContact wersji klasy i jej klas podrzędnych (takich jak CNMutablePostalAddress).

Na przykład poniższy kod utworzy nowy kontakt i doda go do kolekcji kontaktów użytkownika:

// 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);
}

Jeśli ten kod zostanie uruchomiony na urządzeniu z systemem iOS 9, do kolekcji użytkownika zostanie dodany nowy kontakt. Na przykład:

Nowy kontakt dodany do kolekcji użytkownika

Formatowanie i lokalizacja kontaktu

Platforma Kontakty zawiera kilka obiektów i metod, które mogą ułatwić formatowanie i lokalizowanie zawartości do wyświetlania użytkownikowi. Na przykład następujący kod poprawnie sformatowałby nazwę kontaktów i adres wysyłkowy do wyświetlenia:

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

W przypadku etykiet właściwości, które będą wyświetlane w interfejsie użytkownika aplikacji, platforma Contact zawiera również metody lokalizowania tych ciągów. Ponownie jest to oparte na bieżących ustawieniach regionalnych urządzenia z systemem iOS, na których jest uruchamiana aplikacja. Na przykład:

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

Pobieranie istniejących kontaktów

Korzystając z wystąpienia CNContactStore klasy, można pobrać informacje kontaktowe z bazy danych kontaktów użytkownika. Zawiera CNContactStore wszystkie metody wymagane do pobierania lub aktualizowania kontaktów i grup z bazy danych. Ponieważ te metody są synchroniczne, zaleca się uruchomienie ich w wątku w tle, aby uniemożliwić blokowanie interfejsu użytkownika.

Używając predykatów (utworzonych na podstawie CNContact klasy), można filtrować wyniki zwracane podczas pobierania kontaktów z bazy danych. Aby pobrać tylko kontakty zawierające ciąg Appleseed, użyj następującego kodu:

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

Ważne

Predykaty ogólne i złożone nie są obsługiwane przez platformę Kontakty.

Aby na przykład ograniczyć pobieranie tylko do właściwości GivenName i FamilyName kontaktu, użyj następującego kodu:

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

Na koniec, aby przeszukać bazę danych i zwrócić wyniki, użyj następującego kodu:

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

Jeśli ten kod został uruchomiony po przykładzie utworzonym w powyższej sekcji Obiekt kontaktów, zwróci on właśnie utworzony kontakt "John Appleseed".

Prywatność dostępu do kontaktów

Ponieważ użytkownicy końcowi mogą udzielać lub odmawiać dostępu do informacji kontaktowych na podstawie poszczególnych aplikacji, po raz pierwszy wykonasz połączenie z CNContactStoreusługą , zostanie wyświetlone okno dialogowe z prośbą o zezwolenie na dostęp do aplikacji.

Żądanie uprawnień zostanie wyświetlone tylko raz, przy pierwszym uruchomieniu aplikacji, a kolejne uruchomienia lub wywołania do obiektu będą używać CNContactStore uprawnienia wybranego w tym czasie przez użytkownika.

Należy zaprojektować aplikację tak, aby bezpiecznie obsługiwała użytkownika odmawiającego dostępu do bazy danych kontaktów.

Pobieranie częściowych kontaktów

Kontakt częściowy to kontakt, dla którego pobrano tylko niektóre z dostępnych właściwości z magazynu kontaktów. Jeśli spróbujesz uzyskać dostęp do właściwości, która nie została wcześniej pobrana, spowoduje to wyjątek.

Możesz łatwo sprawdzić, czy dany kontakt ma żądaną właściwość przy użyciu IsKeyAvailable metod CNContact lub AreKeysAvailable wystąpienia. Na przykład:

// 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);
}

Ważne

Metody GetUnifiedContactCNContactStore i GetUnifiedContacts klasy zwracają tylko częściowy kontakt ograniczony do właściwości żądanych z podanych kluczy pobierania.

Ujednolicone kontakty

Użytkownik może mieć różne źródła informacji kontaktowych dla jednej osoby w bazie danych kontaktów (takich jak iCloud, Facebook lub Google Mail). W aplikacjach dla systemów iOS i OS X te informacje kontaktowe będą automatycznie połączone i wyświetlane użytkownikowi jako pojedynczy, Ujednolicony kontakt:

Omówienie ujednoliconych kontaktów

Ten ujednolicony kontakt to tymczasowy, w pamięci widok informacji kontaktowych linku, który otrzyma własny unikatowy identyfikator (który powinien zostać użyty do ponownego pobrania kontaktu, jeśli jest to wymagane). Domyślnie platforma Kontakty zwróci ujednolicony kontakt zawsze, gdy jest to możliwe.

Tworzenie i aktualizowanie kontaktów

Jak pokazano w powyższej sekcji Obiekty kontaktu, należy użyć CNContactStore klasy i , CNMutableContact aby utworzyć nowe kontakty, które są następnie zapisywane w bazie danych kontaktów użytkownika przy użyciu elementu 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);
}

Element CNSaveRequest może również służyć do buforowania wielu zmian kontaktów i grup w jednej operacji i dzielenia tych modyfikacji na .CNContactStore

Aby zaktualizować niemodalny kontakt uzyskany z operacji pobierania, należy najpierw zażądać kopii modyfikowalnej, którą następnie zmodyfikujesz i zapiszesz z powrotem w magazynie kontaktów. Na przykład:

// 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);
}

Powiadomienia o zmianie kontaktu

Za każdym razem, gdy kontakt zostanie zmodyfikowany, sklep kontaktowy opublikuje element w CNContactStoreDidChangeNotification domyślnym Centrum powiadomień. Jeśli masz buforowane lub aktualnie wyświetlasz jakiekolwiek kontakty, musisz odświeżyć te obiekty ze sklepu kontaktowego (CNContactStore).

Kontenery i grupy

Kontakty użytkownika mogą istnieć lokalnie na urządzeniu użytkownika lub jako kontakty synchronizowane z urządzeniem z co najmniej jednego konta serwera (na przykład Facebook lub Google). Każda pula kontaktów ma własny kontener , a dany kontakt może istnieć tylko w jednym kontenerze.

Omówienie kontenerów i grup

Niektóre kontenery umożliwiają rozmieszczenie kontaktów w co najmniej jednej grupie lub podgrupach. To zachowanie zależy od magazynu kopii zapasowych dla danego kontenera. Na przykład usługa iCloud ma tylko jeden kontener, ale może mieć wiele grup (ale bez podgrup). Z drugiej strony program Microsoft Exchange nie obsługuje grup, ale może mieć wiele kontenerów (po jednym dla każdego folderu programu Exchange).

Nakładanie się na kontenery i grupy

Struktura ContactsUI

W sytuacjach, w których aplikacja nie musi prezentować niestandardowego interfejsu użytkownika, możesz użyć struktury ContactsUI do prezentowania elementów interfejsu użytkownika do wyświetlania, edytowania, wybierania i tworzenia kontaktów w aplikacji platformy Xamarin.iOS.

Korzystając z wbudowanych kontrolek firmy Apple, nie tylko zmniejszasz ilość kodu, który musisz utworzyć, aby obsługiwać kontakty w aplikacji platformy Xamarin.iOS, ale prezentujesz spójny interfejs użytkownikom aplikacji.

Kontroler widoku selektora kontaktów

Kontroler widoku selektora kontaktów (CNContactPickerViewController) zarządza standardowym widokiem selektora kontaktów, który umożliwia użytkownikowi wybranie właściwości Kontakt lub Kontakt z bazy danych kontaktów użytkownika. Użytkownik może wybrać co najmniej jeden kontakt (na podstawie jego użycia), a kontroler widoku selektora kontaktów nie wyświetla monitu o uprawnienie przed wyświetleniem selektora.

Przed wywołaniem CNContactPickerViewController klasy należy zdefiniować właściwości, które użytkownik może wybrać i zdefiniować predykaty w celu kontrolowania wyświetlania i wybierania właściwości kontaktu.

Użyj wystąpienia klasy dziedziczonej z CNContactPickerDelegate , aby reagować na interakcję użytkownika z selektorem. Na przykład:

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
    }
}

Aby zezwolić użytkownikowi na wybranie adresu e-mail z kontaktów w bazie danych, możesz użyć następującego kodu:

// 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);

Kontroler widoku kontaktu

Klasa Kontroler widoku kontaktu (CNContactViewController) udostępnia kontroler do prezentowania użytkownikowi końcowemu standardowego widoku kontaktu. Widok Kontakt może wyświetlać nowe kontakty Nowe, Nieznane lub Istniejące, a typ musi zostać określony przed wyświetleniem widoku przez wywołanie poprawnego konstruktora statycznego (FromNewContact, FromUnknownContact, FromContact). Na przykład:

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

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

Podsumowanie

W tym artykule szczegółowo przedstawiono pracę ze strukturami interfejsu użytkownika kontaktów i kontaktów w aplikacji platformy Xamarin.iOS. Po pierwsze omówił różne typy obiektów zapewnianych przez platformę Kontakt oraz sposób ich używania do tworzenia nowych lub uzyskiwania dostępu do istniejących kontaktów. Przeanalizowała również strukturę interfejsu użytkownika kontaktów, aby wybrać istniejące kontakty i wyświetlić informacje kontaktowe.