La réponse courte est malheureusement non, ce n'est pas possible .
La réponse est longue : CNMutableContact
est une sous-classe de CNContact
qui dispose de l'interface publique suivante.
open class CNContact : NSObject, NSCopying, NSMutableCopying, NSSecureCoding {
open var identifier: String { get }
open var contactType: CNContactType { get }
open var namePrefix: String { get }
open var givenName: String { get }
open var middleName: String { get }
open var familyName: String { get }
open var previousFamilyName: String { get }
open var nameSuffix: String { get }
open var nickname: String { get }
open var organizationName: String { get }
open var departmentName: String { get }
open var jobTitle: String { get }
open var phoneticGivenName: String { get }
open var phoneticMiddleName: String { get }
open var phoneticFamilyName: String { get }
open var phoneticOrganizationName: String { get }
open var note: String { get }
open var imageData: Data? { get }
open var thumbnailImageData: Data? { get }
open var imageDataAvailable: Bool { get }
open var phoneNumbers: [CNLabeledValue<CNPhoneNumber>] { get }
open var emailAddresses: [CNLabeledValue<NSString>] { get }
open var postalAddresses: [CNLabeledValue<CNPostalAddress>] { get }
open var urlAddresses: [CNLabeledValue<NSString>] { get }
open var contactRelations: [CNLabeledValue<CNContactRelation>] { get }
open var socialProfiles: [CNLabeledValue<CNSocialProfile>] { get }
open var instantMessageAddresses: [CNLabeledValue<CNInstantMessageAddress>] { get }
open var birthday: DateComponents? { get }
open var nonGregorianBirthday: DateComponents? { get }
open var dates: [CNLabeledValue<NSDateComponents>] { get }
/* [...] functions */
}
La seule différence nécessaire entre les deux types (ce qui les rend mutables) est qu'en dehors de l'élément identifier
la propriété CNMutableContact
ne sont pas spécifiées en tant que propriétés "get-only". En y regardant de plus près, vous pouvez maintenant voir qu'il n'y a pas de possibilité de propriétés personnalisées sur les objets Contact. En sous-classant l'objet CNMutableContact
comme je l'ai fait dans l'exemple suivant. nilError et le CNContactStore
ne pas stocker notre contact personnalisé.
func saveCustomContact() {
let contactStore = CNContactStore()
let contact = MyContact()
contact.givenName = "John"
contact.familyName = "Doe"
contact.test = "Hello World"
do {
let saveRequest = CNSaveRequest()
saveRequest.add(contact, toContainerWithIdentifier: nil)
try contactStore.execute(saveRequest)
} catch {
print(error)
}
}
func retrieveCustomContact() {
DispatchQueue.global().async {
let keysToFetch = [CNContactFormatter.descriptorForRequiredKeys(for: .fullName),CNContactPhoneNumbersKey] as [Any]
let fetchRequest = CNContactFetchRequest( keysToFetch: keysToFetch as! [CNKeyDescriptor])
CNContact.localizedString(forKey: CNLabelPhoneNumberiPhone)
fetchRequest.mutableObjects = false
fetchRequest.unifyResults = true
fetchRequest.sortOrder = .userDefault
do {
try CNContactStore().enumerateContacts(with: fetchRequest) { (contact, stop) -> Void in
guard let contact = contact as? MyContact else { print("damn - it's not working!"); return }
print(contact.test)
}
} catch {
print(error)
}
}
}
open class MyContact: CNMutableContact {
open var test: String?
}
Cela m'amène à la conclusion qu'Apple ne veut pas que nous stockions les champs personnalisés dans le carnet de contact par défaut, ce qui est facilement compréhensible du point de vue de la synchronisation (sérialisation/désérialisation).