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