Post

Replies

Boosts

Views

Activity

Reply to unifiedContacts identifier vs contactRelations identifier
Here's the test code where I was attempting to find the relationship between records. // ContentView.swift // TestContactsProject // import SwiftUI import Contacts import OSLog extension Logger { private static var subsystem = Bundle.main.bundleIdentifier ?? "com.myelin.TestContactsProject" static let logic = Logger(subsystem: subsystem, category: "logic") static let analitics = Logger(subsystem: subsystem, category: "analitics") } struct ContentView: View { var body: some View { Text("Hello, World!") .padding() .onAppear { Task.init { await fetchAllContacts() //await fetchSpecificContacts() } } } func fetchSpecificContacts(keyStrings: [String]) { // Run this in the background async // Get access to the Contacts Store let store = CNContactStore() // Keys to fetch let keys = [CNContactGivenNameKey, CNContactFamilyNameKey, CNContactPhoneNumbersKey, CNContactIdentifierKey, CNContactRelationsKey] as [CNKeyDescriptor] // Search criteria let predicate = CNContact.predicateForContacts(withIdentifiers: keyStrings) do { // Perform fetch Logger.logic.trace( " - Looking for \(keyStrings)" ) let contacts = try store.unifiedContacts(matching: predicate, keysToFetch: keys) Logger.logic.trace ("\(contacts)") } catch { // If there was an error, Handle it here Logger.logic.trace("Error") } } func fetchAllContacts() async { // Run this in the background async // Get access to the Contacts Store let store = CNContactStore() // Specify which data keys we want to fetch let keys = [CNContactGivenNameKey, CNContactFamilyNameKey, CNContactPhoneNumbersKey, CNContactIdentifierKey, CNContactRelationsKey] as [CNKeyDescriptor] // Create Fetch Request let fetchRequest = CNContactFetchRequest(keysToFetch: keys) fetchRequest.unifyResults = false // CHANGE - Try to find a way to look for both unified and non-unified contacts // per https://developer.apple.com/forums/thread/694471?answerId=694923022#694923022 // Specify which data keys we want to return do { try store.enumerateContacts(with: fetchRequest, usingBlock: { contact, results in // Do something with the contact Logger.logic.trace("Name: \(contact.givenName) \(contact.familyName)") Logger.logic.trace(" \(contact.id)") for number in contact.phoneNumbers { switch number.label { case CNLabelPhoneNumberMobile: Logger.logic.trace("- Mobile: \(number.value.stringValue)") case CNLabelPhoneNumberMain: Logger.logic.trace("- Main : \(number.value.stringValue)") default: Logger.logic.trace("- Other : \(number.value.stringValue)") } for relation in contact.contactRelations { switch relation.label { case CNLabelContactRelationSpouse: Logger.logic.trace("- Spouse: \(relation.value)") Logger.logic.trace("- \(relation.identifier)") fetchSpecificContacts(keyStrings: [relation.identifier]) case CNLabelContactRelationMother: Logger.logic.trace("- Mother: \(relation.value)") Logger.logic.trace("- \(relation.identifier)") fetchSpecificContacts(keyStrings: [relation.identifier]) default: Logger.logic.trace("- Other: \(relation.value)") Logger.logic.trace("- \(relation)") Logger.logic.trace("- \(relation.identifier)") } } } }) } catch { // If there was an error, Handle it here Logger.logic.trace("Error") } } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } }
Topic: App & System Services SubTopic: General Tags:
Dec ’25