스트리밍은 대부분의 브라우저와
Developer 앱에서 사용할 수 있습니다.
-
Contact Access Button 소개
새로운 연락처 승인 모드에 대해 알아보고, 앱에서 연락처 접근을 향상하는 방법을 확인해 보세요. Contact Access Button을 앱에 통합하여 요청에 따라 추가 연락처를 공유하고 간편한 연락처 승인 방법을 제공하는 방법을 살펴보세요. 또한 Contact Access Button이 앱에 적합하지 않은 경우 사용할 수 있는 대체 API와 연락처 보안 기능도 설명합니다.
챕터
- 0:00 - Introduction
- 0:36 - Limited Access
- 2:56 - Contact Access Button
- 8:28 - Accessing contacts
- 13:34 - Which access method to use
리소스
-
다운로드
안녕하세요! Ada입니다 이 비디오에서는 Contact Access Button과 앱에서 이를 사용하는 방법을 간략히 소개하려고 합니다 먼저, iOS 18에서 제공되는 제한된 접근 권한 기능의 개요를 살펴보겠습니다 그런 다음, 새로운 ContactAccessButton API와 앱에서 바로 이 API를 사용하여 멋진 연락처 경험을 선사하는 방법을 설명하겠습니다! 마지막으로, 연락처에 접근하는 다른 방법들과 제한된 접근 권한 기능을 사용하는 방법을 알아보겠습니다
iOS 18에서는 연락처 승인에 연락처 데이터베이스의 일부만 공유할 수 있는 옵션이 제공됩니다 이를 제한된 접근 권한이라고 합니다 이제 연락처 승인 프롬프트가 두 단계로 제공됩니다 첫 번째 알림은 연락처를 앱과 공유할지 여부를 물어봅니다 계속을 탭하면 두 번째 프롬프트가 표시되어 연락처 공유를 위한 두 가지 옵션이 제공됩니다 공유할 연락처 세트를 선택하거나 앱에 모든 항목에 대한 접근 권한을 제공할 수 있습니다 프롬프트에서는 이것이 최종 선택이 아니며 이후 연락처 세트를 확장할 수 있음을 강조합니다
원하는 연락처 세트를 선택하면 확인 화면에 선택된 연락처가 표시됩니다 이 새로운 승인 흐름은 공유되는 항목에 대한 투명성과 제어력을 통해 연락처 개인정보 보호를 크게 향상합니다
이 새로운 기능에는 4개의 승인 수준이 있습니다 전체 접근 권한이 있는 경우 앱이 모든 연락처를 읽을 수 있고 연락처를 수정하거나 새 연락처를 만들 수도 있습니다
제한된 접근 권한이 있는 경우 앱이 접근 권한이 부여된 연락처를 읽을 수 있습니다 전체 접근 권한처럼, 앱이 연락처를 수정하거나 만들 수 있죠
앱은 항상 ‘확인되지 않음’ 승인 상태로 시작됩니다 연락처 저장소에 접근하려고 하면 승인 프롬프트가 모달 형식으로 표시됩니다
앱이 승인된 경우 접근 시도가 성공합니다
마지막으로, 앱이 ‘거부됨’ 승인 수준인 경우에는 연락처 데이터를 읽거나 쓸 수 없습니다
접근이 제한되는 경우 멋진 경험을 선사할 수 있도록 iOS 18에는 앱에 추가 연락처에 대한 접근 권한을 부여할 수 있는 2개의 새로운 API가 포함됩니다 연락처 접근 선택기를 사용하면 앱이 접근할 수 있는 연락처를 쉽게 변경할 수 있습니다 앱을 종료하지 않아도 됩니다
Contact Access Button은 앱에서 바로 연락처에 대한 접근 권한을 관리할 수 있는 강력하고 새로운 방법입니다 화면 전체 선택기 대신에 이 버튼은 기존 UI 내에 배치되며 탭 한 번으로 새 연락처에 대한 접근 권한을 부여할 수 있습니다 이제 연락처 접근에 대한 기본적인 사항을 이해했으니 앱에서 제한된 접근 권한을 처리하는 최고의 방법을 살펴보죠 바로 Contact Access Button입니다! ContactAccessButton은 앱에서 추가 연락처에 대한 접근 권한을 받을 수 있는 간소화된 방법을 나타냅니다
이 버튼을 앱의 연락처 검색 흐름에 추가하면 이 버튼 사용 시 앱에 아직 접근 권한이 없는 연락처에 대한 검색 결과를 표시합니다 이 버튼은 앱에 일부로 매끄럽게 통합됩니다
버튼 사용 시 일치하는 항목이 하나인 경우 탭 한 번만으로 해당 연락처 접근 권한을 앱에 부여할 수 있죠 앱에서 모든 기능을 갖춘 연락처 선택기 경험을 제공하며 전체 접근 권한이 필요하지 않습니다
제한된 접근 권한에 대한 이러한 증분 접근 방식 덕분에 필요한 경우 정확히 필요한 연락처에 대한 접근 권한만 앱에 제공됩니다 따라서 사용자가 더 확실하게 연락처를 앱과 공유할 수 있습니다
승인을 요청할 수 있는 최고의 시점은 상호작용에 접근 권한이 필요한 순간입니다 데이터가 필요한 시점에 요청하면 접근 권한이 부여될 경우 앱이 어떤 기능을 제공할지가 명확합니다
Contact Access Button은 이 원칙을 중심으로 디자인됩니다 이 버튼을 사용하면 각 연락처가 공유되어야 할 명확한 필요성이 있는 경우 접근 권한을 요청하는 워크플로를 중심으로 앱이 작동합니다
이 버튼을 사용하면 사용자가 앱에 어떤 연락처가 필요할지 추측하도록 하는 대신에 사용자가 공유하려는 연락처를 정확히 알 수 있는 맥락 안에서 결정할 수 있습니다
Contact Access Button은 여기서 한 단계 더 나아갑니다 앱의 승인 수준이 여전히 ‘확인되지 않음’인 상태에서도 표시될 수 있습니다
앱에 권한이 승인되기 전에 이 버튼을 탭하면 제한된 접근 권한을 요청하는 간소화된 프롬프트가 자동으로 표시되죠 연락처 검색 결과를 탭하는 즉시 발생하므로 앱에 접근 권한이 필요한 이유를 쉽게 이해할 수 있으며 앱에 접근 권한이 부여될 가능성이 훨씬 더 높습니다
앱에서 이 버튼을 사용하는 방법의 예제를 살펴보죠 앱에서 연락처 검색 결과를 보여 주는 간단한 뷰입니다
이 뷰는 앱의 검색 텍스트 필드에 입력된 텍스트에 바인딩됩니다
또한 앱의 승인 상태를 추적합니다
먼저, 앱 자체 데이터 저장소에서 검색할 수 있는 결과를 표시합니다 여기서는 간단한 ForEach를 사용해 이를 수행합니다
앱의 자체 결과를 표시한 후 Contact Access Button을 조건부로 표시합니다 즉, 앱이 limited나 notDetermined 승인 상태인 경우에만 표시합니다
버튼을 초기화하면 검색 필드에 입력된 텍스트를 전달합니다
마지막으로, 콜백 블록에서는 연락처 식별자 문자열 배열을 수신합니다 이때, 연락처 세부 정보를 검색하고 검색 UI를 닫을 수 있습니다
이 버튼은 앱의 디자인에 맞게 맞춤화할 수 있도록 디자인되며 이를 위해 표준 SwiftUI 한정자를 사용합니다
서체 한정자는 텍스트 상단 줄과 이후 동작 레이블의 디자인을 제어합니다
foregroundStyle 한정자가 주요 텍스트의 색상을 변경합니다
동작 레이블은 앱의 색조 색상을 사용합니다
마지막으로, 몇 가지 버튼별 한정자가 있습니다 일치하는 항목이 하나 있는 경우 버튼이 해당 일치하는 연락처의 정보 중 일부를 표시할 수 있으며 이는 contactAccessButtonCaption 한정자로 지정할 수 있습니다
연락처 사진의 크기도 맞춤화할 수 있으며 이때 contactAccessButtonStyle 한정자를 사용합니다
연락처 버튼은 앱이 개인정보를 철저히 보호하면서 추가 접근 권한을 얻을 수 있는 강력하고 편리한 방법입니다 앱이 해당 접근 권한을 얻기 전에 버튼이 민감한 정보를 표시하므로 버튼의 콘텐츠는 비공개로 유지되나 앱에서 볼 수 있습니다
또한 이 버튼은 검증된 이벤트에만 응답합니다
마지막으로, 이 버튼은 콘텐츠가 명확하게 읽을 수 있고 가려지지 않은 경우 탭할 때에만 접근 권한을 부여합니다 따라서 버튼을 탭하면 어떤 작업이 수행될지 항상 명확히 알 수 있죠
버튼은 읽을 수 있고 가려지지 않아야 합니다 그렇지 않으면 버튼이 추가 연락처 접근 권한을 앱에 부여하지 않죠
먼저, 전경과 배경이 명확한 대비를 이루고 렌더링할 공간이 충분하며 전체 버튼이 표시되도록 구성된 버튼의 예제입니다 이 예제는 버튼 가독성에 대한 모든 요구 사항을 충족합니다 그 아래에는 부적절하게 구성된 버튼 예제가 나와 있습니다 텍스트와 배경 사이의 명암비가 매우 낮습니다 흰색 배경에 연한 회색 텍스트가 사용되었네요
버튼의 일부가 잘려서 버튼을 가립니다
이 버튼은 탭했을 때 연락처 접근 권한을 부여하지 않겠네요
항상 Contact Access Button이 읽을 수 있고 가려지지 않은 상태이며 렌더링할 공간이 충분한지 확인하세요
버튼 외에도 Contacts 프레임워크에는 연락처 데이터에 접근하는 3가지 다른 방법이 있습니다 어떻게 작동하는지 살펴보고 이러한 방법을 사용할 때 제한된 접근 권한은 어떤 의미를 갖는지 알아보죠
CNContactStore는 연락처 데이터에 접근할 수 있는 주요 방법입니다 연락처를 가져오고 새 연락처 항목을 생성할 수 있습니다
앱이 연락처 데이터에 접근하려고 하면 CNContactStore가 승인 프롬프트를 자동으로 표시합니다
CNContactStore를 사용해 앱의 승인 수준을 확인하고 이를 사용해 적절한 UI를 표시하세요
연락처 데이터를 읽거나 쓰려고 하면 앱이 승인된 경우에만 성공합니다
또한 연락처 데이터가 변경되면 알려 주며 변경된 사항을 확인하는 데에도 사용될 수 있습니다
접근이 제한되는 경우 연락처 저장소에서 해당 앱과 공유된 연락처 항목을 제공합니다 전체 또는 부분 접근 권한 중 어떤 것이 부여되었는지 파악하며 이를 위해 새로운 .limited 열거형 케이스의 승인 상태를 확인합니다 .limited 상태는 표시할 UI를 결정하기 위해 제공됩니다 이는 ContactAccessButton과 같은 .limited 승인을 위해 디자인된 새 Contacts API를 선택적으로 사용하는 데 유용합니다
마지막으로, CNContactStore는 ContactAccessButton 사용의 필수적인 부분이며 연락처 식별자 배열을 반환합니다 CNContactStore로 해당 식별자를 사용한 연락처 데이터를 검색하죠 어떻게 작동하는지에 대한 예제를 보여 드리겠습니다
여기에 연락처 식별자 문자열 배열을 받고, 해당 식별자가 나타내는 CNContact를 반환하는 함수가 있습니다 메인 액터 블로킹을 방지하기 위해 대기 중인 Task에서 가져오기를 수행합니다
해당 작업 내에서 먼저 CNContactFetchRequest를 생성하며 여기서 가져오려는 연락처 필드의 키를 나열합니다 이 예제에서는 연락처 이름을 표시하는 데 필요한 필드만 가져옵니다
식별자로 연락처를 가져오려면 다음을 사용합니다 CNContact predicateForContacts(withIdentifiers:)
그 후, CNContactStore의 enumerateContacts(with:)를 사용하고 결과를 배열에 수집합니다 다음 연락처 데이터 접근 방법은 CNContactPickerViewController죠 이 뷰 컨트롤러는 연락처 데이터베이스에서 하나 이상의 연락처를 선택하기 위한 시스템 UI를 표시합니다
연락처를 선택한 후 앱이 선택된 연락처의 일회성 스냅샷을 수신합니다 이 뷰 컨트롤러는 앱의 승인 수준에 관계없이 작동하며 항상 전체 연락처 데이터베이스를 표시합니다
사용자 상호작용은 암묵적 권한을 부여하며 선택기에서 하나 이상의 연락처가 선택된 경우 앱이 연락처 데이터를 수신합니다
CNContactPickerViewController는 이메일 주소나 전화번호 선택 등 일회성 작업을 위한 연락처 정보만 필요한 경우 사용하는 것이 가장 좋습니다 연락처가 일시적으로만 앱과 공유되기 때문입니다
iOS 18엔 contactAccessPicker라는 새로운 선택기가 있습니다 이 선택기는 모달 시트를 표시하는데 여기서 앱의 제한된 접근 권한 연락처 세트를 변경할 수 있습니다 contactAccessPicker를 사용해 대량 사용 사례 또는 즉각적이지 않은 사용 사례를 위해 추가 연락처에 접근할 수 있습니다 예를 들어 소셜 앱은 친구 찾기를 위해 추가 연락처를 공유하는 어포던스가 필요할 수 있습니다
contactAccessPicker는 새로 허용된 연락처 식별자를 반환하죠
CNContactPickerViewController와 다른 점입니다 contactAccessPicker는 CNContactStore를 통해 앱이 접근할 수 있는 연락처를 관리하기 위한 것입니다 CNContactPickerViewController는 연락처 데이터의 일회용 스냅샷에 대한 접근 권한을 제공합니다
이를 사용하는 방법의 예제입니다 이 경우에는 State 불리언을 토글하는 간단한 Button이 있죠 contactAccessPicker 메서드를 사용해 불리언이 true일 때 버튼이 선택기를 표시하도록 합니다
마지막으로 콜백 블록에서 앱이 방금 접근 권한을 얻은 연락처를 가져옵니다
ContactAccessButton과 마찬가지로 이 콜백 블록은 연락처 식별자 문자열 배열을 수신하므로 정확히 동일한 방법으로 연락처를 가져옵니다 콜백 블록은 새로 접근할 수 있는 연락처만 보고합니다 지금까지 살펴본 모든 예제는 이 비디오와 연결된 샘플 앱에서 사용할 수 있으며 API가 어떻게 사용되고 있는지 설명하는 주석이 함께 제공됩니다
연락처에 접근할 수 있는 4가지 방법이 있습니다 각각은 승인 수준에 따라 서로 다른 영향을 받으며 이러한 방법을 사용하기에 적합한 경우는 다음과 같습니다
CNContactPickerViewController는 승인 수준에 관계없이 사용할 수 있으며 앱이 뷰 컨트롤러에서 선택된 연락처에 대한 일회성 접근 권한을 얻도록 합니다 항상 그렇습니다 CNContactStore는 연락처 데이터에 접근하는 기본 방법이며 승인이 필요합니다 앱에 전체 권한 승인이 필요한 드문 경우 연락처 데이터를 읽고 쓸 수 있습니다 앱이 제한된 권한 승인 상태인 경우 허용된 세트의 연락처에만 접근할 수 있습니다
앱이 ‘확인되지 않음’ 승인 상태인 경우에는 쿼리 시 CNContactStore가 승인 프롬프트를 표시합니다
앱이 '거부됨 승인 상태이면 연락처 데이터에 접근할 수 없죠 ContactAccessButton은 앱이 제한된 권한 승인 상태인 경우 추가 연락처에 접근하기 위한 것입니다 탭하면 CNContactStore를 사용해 연락처를 검색합니다 이 버튼은 앱이 승인되기 전에도 사용할 수 있습니다 UI의 ContactAccessButton은 제한된 권한 승인 상태인 경우 최고의 방법입니다
contactAccessPicker는 앱의 제한된 접근 권한을 관리하기 위한 것이며, 앱이 제한된 승인 상태인 경우에만 사용해야 합니다
지금까지 모든 연락처 승인 수준과 접근 방법을 알아봤습니다
다음으로 무엇을 해야 할까요? iOS18에서 앱을 실행하고 제한된 접근 권한을 테스트해 보세요 연락처 접근 권한 관리를 위해 ContactAccessButton을 사용하세요 필요할 때 앱의 UI에서 바로 사용할 수 있습니다
여러분의 앱에서 사용자가 연락처 정보를 공유하도록 하려면 어떤 연락처 접근 방법이 가장 좋은지 결정해 보세요
시청해 주셔서 감사합니다!
-
-
5:15 - Using ContactAccessButton
// Using ContactAccessButton @Binding var searchText: String @State var authorizationStatus: CNAuthorizationStatus = .notDetermined var body: some View { List { ForEach(searchResults(for: searchText)) { person in ResultRow(person) } if authorizationStatus == .limited || authorizationStatus == .notDetermined { ContactAccessButton(queryString: searchText) { identifiers in let contacts = await fetchContacts(withIdentifiers: identifiers) dismissSearch(withResult: contacts) } } } }
-
6:10 - Appearance options
ContactAccessButton(queryString: searchText) .font(.system(weight: .bold)) .foregroundStyle(.gray) .tint(.green) .contactAccessButtonCaption(.phone) .contactAccessButtonStyle(ContactAccessButton.Style(imageWidth: 30))
-
10:11 - Fetching contacts with CNContactStore
// Fetching contacts with CNContactStore func fetchContacts(withIdentifiers identifiers: [String]) async -> [CNContact] { return await Task { let keys = [CNContactFormatter.descriptorForRequiredKeys(for: .fullName)] let fetchRequest = CNContactFetchRequest(keysToFetch: keys) fetchRequest.predicate = CNContact.predicateForContacts(withIdentifiers: identifiers) var contacts: [CNContact] = [] do { try CNContactStore().enumerateContacts(with: fetchRequest) { contact, _ in contacts.append(contact) } } catch { // ... } return contacts }.value }
-
12:47 - Using contactAccessPicker
// Using contactAccessPicker @State private var isPresented = false var body: some View { Button("Show picker") { isPresented.toggle() }.contactAccessPicker(isPresented: $isPresented) { identifiers in let contacts = await fetchContacts(withIdentifiers: identifiers) // use the new contacts! } }
-
-
찾고 계신 콘텐츠가 있나요? 위에 주제를 입력하고 원하는 내용을 바로 검색해 보세요.
쿼리를 제출하는 중에 오류가 발생했습니다. 인터넷 연결을 확인하고 다시 시도해 주세요.