2024 SwiftUI & UI FrameworksApp Services
WWDC24 · 16 min · SwiftUI & UI Frameworks / App Services
Meet the Contact Access Button
Learn about the new Contacts authorization modes and how to improve Contacts access in your app. Discover how to integrate the Contact Access Button into your app to share additional contacts on demand and provide an easier path to Contacts authorization. We’ll also cover Contacts security features and an alternative API to be used if the button isn’t appropriate for your app.
Watch at developer.apple.com ↗Chapters
Code shown on screen · 4 snippets
Using ContactAccessButton
// Using ContactAccessButton
var searchText: String
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)
}
}
}
} Appearance options
ContactAccessButton(queryString: searchText)
.font(.system(weight: .bold))
.foregroundStyle(.gray)
.tint(.green)
.contactAccessButtonCaption(.phone)
.contactAccessButtonStyle(ContactAccessButton.Style(imageWidth: 30)) 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
} Using contactAccessPicker
// Using contactAccessPicker
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!
}
}