Xamarin.iOS의 연락처 및 연락처UI

이 문서에서는 Xamarin.iOS 앱에서 새 연락처 및 연락처 UI 프레임워크를 사용하는 작업에 대해 설명합니다. 이러한 프레임워크는 이전 버전의 iOS에서 사용된 기존 주소록 및 주소록 UI를 대체합니다.

iOS 9의 도입으로 Apple은 iOS 8 이하에서 사용하는 기존 주소록 및 주소록 UI 프레임워크를 대체하는 두 가지 새로운 프레임워크 ContactsContactsUI를 출시했습니다.

두 개의 새 프레임워크에는 다음 기능이 포함되어 있습니다.

  • 연락처 - 사용자의 연락처 목록 데이터에 대한 액세스를 제공합니다. 대부분의 앱은 읽기 전용 액세스만 필요하므로 이 프레임워크는 스레드로부터 안전한 읽기 전용 액세스에 최적화되었습니다.

  • ContactsUI - iOS 디바이스에서 연락처를 표시, 편집, 선택 및 만들 수 있는 Xamarin.iOS UI 요소를 제공합니다.

An example Contact Sheet on an iOS device

Important

iOS 8(및 이전)에서 사용하는 기존 AddressBookAddressBookUI 프레임워크는 iOS 9에서 더 이상 사용되지 않으며, 기존 Xamarin.iOS 앱에 대해 가능한 한 빨리 새로운 ContactsUIContacts 프레임워크로 대체해야 합니다. 새 앱은 새 프레임워크에 대해 작성해야 합니다.

다음 섹션에서는 이러한 새 프레임워크와 Xamarin.iOS 앱에서 구현하는 방법을 살펴보겠습니다.

Contacts 프레임워크

Contacts Framework는 사용자의 연락처 정보에 대한 Xamarin.iOS 액세스를 제공합니다. 대부분의 앱은 읽기 전용 액세스만 필요하므로 이 프레임워크는 스레드로부터 안전한 읽기 전용 액세스에 최적화되었습니다.

연락처 개체

이 클래스는 CNContact 이름, 주소 또는 전화 번호와 같은 연락처의 속성에 대한 스레드로부터 안전한 읽기 전용 액세스를 제공합니다. CNContact 는 a와 같은 NSDictionary 함수이며 주소 또는 전화 번호와 같은 여러 읽기 전용 속성 컬렉션을 포함합니다.

Contact Object overview

여러 값(예: 전자 메일 주소 또는 전화 번호)을 가질 수 있는 속성의 경우 개체 배열 NSLabeledValue 로 표시됩니다. NSLabeledValue 는 레이블이 사용자에게 값을 정의하는 읽기 전용 레이블 및 값 집합으로 구성된 스레드로부터 안전한 튜플입니다(예: 홈 또는 회사 전자 메일). Contacts 프레임워크는 앱에서 사용할 수 있는 미리 정의된 레이블(및 CNLabelPhoneNumberKey 정적 클래스를 통해CNLabelKey)을 선택하거나 필요에 따라 사용자 지정 레이블을 정의할 수 있는 옵션을 제공합니다.

기존 연락처의 값을 조정하거나 새 연락처를 만들어야 하는 Xamarin.iOS 앱의 경우 클래스 버전과 해당 하위 클래스(예: CNMutablePostalAddress)를 사용합니다NSMutableContact.

예를 들어 다음 코드는 새 연락처를 만들고 사용자의 연락처 컬렉션에 추가합니다.

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

이 코드가 iOS 9 디바이스에서 실행되는 경우 사용자의 컬렉션에 새 연락처가 추가됩니다. 예시:

A new contact added to the user's collection

연락처 서식 및 지역화

Contacts 프레임워크에는 사용자에게 표시할 콘텐츠의 서식을 지정하고 지역화하는 데 도움이 되는 여러 개체와 메서드가 포함되어 있습니다. 예를 들어 다음 코드는 표시할 연락처 이름과 우편 주소의 서식을 올바르게 지정합니다.

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

앱의 UI에 표시할 속성 레이블의 경우 Contact 프레임워크에는 이러한 문자열을 지역화하는 메서드도 있습니다. 다시 말하지만, 이는 앱이 실행되고 있는 iOS 디바이스의 현재 로캘을 기반으로 합니다. 예시:

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

기존 연락처 가져오기

클래스의 인스턴스를 CNContactStore 사용하여 사용자의 연락처 데이터베이스에서 연락처 정보를 가져올 수 있습니다. 데이터베이스 CNContactStore 에서 연락처 및 그룹을 가져오거나 업데이트하는 데 필요한 모든 메서드가 포함됩니다. 이러한 메서드는 동기적이므로 백그라운드 스레드에서 실행하여 UI를 차단하지 않도록 하는 것이 좋습니다.

조건자(클래스에서 빌드됨)를 사용하여 데이터베이스에서 CNContact 연락처를 가져올 때 반환되는 결과를 필터링할 수 있습니다. 문자열 Appleseed이 포함된 연락처만 가져오려면 다음 코드를 사용합니다.

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

Important

제네릭 및 복합 조건자는 Contacts 프레임워크에서 지원되지 않습니다.

예를 들어 페치를 연락처의 GivenName 및 FamilyName 속성으로만 제한하려면 다음 코드를 사용합니다.

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

마지막으로 데이터베이스를 검색하고 결과를 반환하려면 다음 코드를 사용합니다.

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

이 코드가 위의 Contacts 개체 섹션에서 만든 샘플 이후에 실행된 경우 방금 만든 "John Appleseed" 연락처를 반환합니다.

액세스 개인 정보 보호에 문의

최종 사용자는 애플리케이션별로 연락처 정보에 대한 액세스 권한을 부여하거나 거부할 수 있으므로 처음 전화를 걸 CNContactStore때 앱에 대한 액세스를 허용하도록 요청하는 대화 상자가 표시됩니다.

권한 요청은 앱이 처음 실행될 때 한 번만 표시되며, 후속 실행 또는 호출 CNContactStore 은 해당 시간에 사용자가 선택한 사용 권한을 사용합니다.

연락처 데이터베이스에 대한 액세스를 거부하는 사용자를 정상적으로 처리하도록 앱을 디자인해야 합니다.

부분 연락처 가져오기

부분 연락처는 사용 가능한 속성 중 일부만 연락처 저장소에서 가져온 연락처입니다. 이전에 페치되지 않은 속성에 액세스하려고 하면 예외가 발생합니다.

인스턴스의 메서드 또는 AreKeysAvailable 메서드 CNContact 를 사용하여 IsKeyAvailable 지정된 연락처에 원하는 속성이 있는지 쉽게 검사 수 있습니다. 예시:

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

클래스의 메서드 및 GetUnifiedContacts 메서드는 GetUnifiedContact 제공된 페치 키에서 요청된 속성으로 제한된 부분 연락처만 반환 CNContactStore합니다.

통합 연락처

사용자는 연락처 데이터베이스에 있는 한 사람의 연락처 정보 원본이 다를 수 있습니다(예: iCloud, Facebook 또는 Google Mail). iOS 및 OS X 앱에서 이 연락처 정보는 자동으로 함께 연결되고 단일 통합 연락처사용자에게 표시됩니다.

Unified Contacts overview

이 통합 연락처는 고유한 고유 식별자가 제공될 링크 연락처 정보의 임시 메모리 내 보기입니다(필요한 경우 연락처를 다시 구성하는 데 사용해야 함). 기본적으로 Contacts 프레임워크는 가능하면 통합 연락처를 반환합니다.

연락처 만들기 및 업데이트

위의 연락처 개체 섹션에서 볼 수 있듯이 다음을 사용하여 사용자의 연락처 데이터베이스에 기록되는 새 연락처를 만드는 데 a CNMutableContact 와 인스턴스를 CNSaveRequest사용합니다CNContactStore.

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

또한 A CNSaveRequest 를 사용하여 여러 연락처 및 그룹 변경 내용을 단일 작업으로 캐시하고 이러한 수정 내용을 일괄 처리할 수 CNContactStore있습니다.

페치 작업에서 가져온 변경할 수 없는 연락처를 업데이트하려면 먼저 변경 가능한 복사본을 요청한 다음 수정하여 연락처 저장소에 다시 저장해야 합니다. 예시:

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

연락처 변경 알림

연락처가 수정될 때마다 연락처 저장소는 기본 알림 센터에 게시 CNContactStoreDidChangeNotification 합니다. 캐시했거나 현재 연락처를 표시하는 경우 연락처 저장소(CNContactStore)에서 해당 개체를 새로 고쳐야 합니다.

컨테이너 및 그룹

사용자의 연락처는 사용자의 디바이스에 로컬로 존재하거나 하나 이상의 서버 계정(예: Facebook 또는 Google)에서 디바이스에 동기화된 연락처로 존재할 수 있습니다. 각 연락처 풀에는 자체 컨테이너 가 있으며 지정된 연락처는 하나의 컨테이너에만 존재할 수 있습니다.

Containers and Groups overview

일부 컨테이너를 사용하면 연락처를 하나 이상의 그룹 또는 하위 그룹으로 정렬할 수 있습니다. 이 동작은 지정된 컨테이너에 대한 백업 저장소에 따라 달라집니다. 예를 들어 iCloud에는 컨테이너가 하나만 있지만 여러 그룹(하위 그룹은 없음)이 있을 수 있습니다. 반면 Microsoft Exchange는 그룹을 지원하지 않지만 여러 컨테이너(각 Exchange 폴더에 대해 하나씩)를 가질 수 있습니다.

Overlap within Containers and Groups

ContactsUI 프레임워크

애플리케이션에서 사용자 지정 UI를 표시할 필요가 없는 경우 ContactsUI 프레임워크를 사용하여 Xamarin.iOS 앱에서 연락처를 표시, 편집, 선택 및 만드는 UI 요소를 표시할 수 있습니다.

Apple의 기본 제공 컨트롤을 사용하면 Xamarin.iOS 앱에서 연락처를 지원하기 위해 만들어야 하는 코드의 양을 줄일 뿐만 아니라 앱 사용자에게 일관된 인터페이스를 제공합니다.

연락처 선택 보기 컨트롤러

연락처 선택기 보기 컨트롤러(CNContactPickerViewController)는 사용자가 사용자의 연락처 데이터베이스에서 연락처 또는 연락처 속성을 선택할 수 있도록 하는 표준 연락처 선택기 보기를 관리합니다. 사용자는 사용량에 따라 하나 이상의 연락처를 선택할 수 있으며 선택기를 표시하기 전에 연락처 선택기 보기 컨트롤러에서 사용 권한을 묻는 메시지가 표시되지 않습니다.

클래스를 CNContactPickerViewController 호출하기 전에 사용자가 선택할 수 있는 속성을 정의하고 조건자를 정의하여 연락처 속성의 표시 및 선택을 제어합니다.

사용자가 선택기를 조작하는 데 응답하기 위해 상속 CNContactPickerDelegate 되는 클래스의 인스턴스를 사용합니다. 예시:

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

사용자가 데이터베이스의 연락처에서 전자 메일 주소를 선택할 수 있도록 하려면 다음 코드를 사용할 수 있습니다.

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

연락처 뷰 컨트롤러

연락처 뷰 컨트롤러(CNContactViewController) 클래스는 최종 사용자에게 표준 연락처 보기를 제공하는 컨트롤러를 제공합니다. 연락처 보기는 새 새 연락처, 알 수 없음 또는 기존 연락처를 표시할 수 있으며 올바른 정적 생성자(FromNewContact, FromUnknownContact, FromContact)를 호출하여 보기를 표시하기 전에 유형을 지정해야 합니다. 예를 들면 다음과 같습니다.

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

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

요약

이 문서에서는 Xamarin.iOS 애플리케이션에서 연락처 및 연락처 UI 프레임워크를 사용하는 자세한 내용을 살펴보았습니다. 먼저 연락처 프레임워크에서 제공하는 다양한 유형의 개체와 이를 사용하여 새 연락처를 만들거나 기존 연락처에 액세스하는 방법을 설명했습니다. 또한 연락처 UI 프레임워크를 검사하여 기존 연락처를 선택하고 연락처 정보를 표시했습니다.