更新联系人失败

huangapple go评论72阅读模式
英文:

swift update contact fails

问题

在我的应用程序中,我从客户那里收集数据,如姓名、地址、电话号码等。我想提供一个按钮,用于将这些数据保存并更新到苹果的联系人应用程序。

因此,我编写了这个类:

class ContactsClass {
    func addToContacts(
        lastName: String,
        firstName: String,
        mail: String = "",
        phone1: String = "",
        street: String,
        city: String,
        postCode: String
    ) {
        // 创建一个可变对象以添加到联系人
        let contact = CNMutableContact()
            
        contact.givenName = firstName
        contact.familyName = lastName
        
        if mail != "" {
            let homeEmail = CNLabeledValue(label: CNLabelHome, value: mail as NSString)
            contact.emailAddresses = [homeEmail]
        }
        
        contact.phoneNumbers = []
        if phone1 != "" {
            contact.phoneNumbers.append(CNLabeledValue(label: CNLabelPhoneNumberMain, value: CNPhoneNumber(stringValue: phone1)))
        }

        let homeAddress = CNMutablePostalAddress()
        homeAddress.street = street
        homeAddress.city = city
        homeAddress.postalCode = postCode
        contact.postalAddresses = [CNLabeledValue(label: CNLabelHome, value: homeAddress)]

        // 保存新创建的联系人
        let store = CNContactStore()
        let saveRequest = CNSaveRequest()
        saveRequest.add(contact, toContainerWithIdentifier: gruppe)
        do {
            try store.execute(saveRequest)
        } catch {
            print("保存联系人失败,错误:\(error)")
            // 处理错误
        }
    }
    
    func checkForExistingContact(familyName: String, givenName: String) -> CNContact? {
        let store = CNContactStore()
        do {
            let predicate = CNContact.predicateForContacts(matchingName: familyName)
            let keysToFetch = [CNContactGivenNameKey, CNContactFamilyNameKey, CNContactEmailAddressesKey] as [CNKeyDescriptor]
            let contacts = try store.unifiedContacts(matching: predicate, keysToFetch: keysToFetch)
            for contact in contacts {
                if contact.givenName == givenName {
                    return contact
                }
            }
            return nil
        } catch {
            return nil
        }
    }
    
    func updateContact(
        contact: CNContact,
        lastName: String,
        firstName: String,
        mail: String = "",
        phone1: String = "",
        street: String,
        city: String,
        postCode: String
    ) {
        let mutableContact = contact.mutableCopy() as! CNMutableContact
            
        mutableContact.givenName = firstName
        mutableContact.familyName = lastName
        
        if mail != "" {
            let homeEmail = CNLabeledValue(label: CNLabelHome, value: mail as NSString)
            mutableContact.emailAddresses = [homeEmail]
        }
        
        mutableContact.phoneNumbers = []
        if phone1 != "" {
            mutableContact.phoneNumbers.append(CNLabeledValue(label: CNLabelPhoneNumberMain, value: CNPhoneNumber(stringValue: phone1)))
        }
        
        let homeAddress = CNMutablePostalAddress()
        homeAddress.street = street
        homeAddress.city = city
        homeAddress.postalCode = postCode
        mutableContact.postalAddresses = [CNLabeledValue(label: CNLabelHome, value: homeAddress)]
        
        // 保存已更新的联系人
        let store = CNContactStore()
        let saveRequest = CNSaveRequest()
        saveRequest.update(mutableContact)
        do {
            try store.execute(saveRequest)
        } catch {
            print("保存联系人失败,错误:\(error)")
            // 处理错误。
        }
    }
}

我的按钮调用了这个函数:

private func addToContacts() {
    let con = ContactsClass()
    
    if let contact = con.checkForExistingContact(familyName: klient.nachname!, givenName: klient.vorname!) {
        con.updateContact(
            contact: contact,
            lastName: klient.nachname!,
            firstName: klient.vorname!,
            mail: klient.email ?? "",
            phone1: klient.telefon1 ?? "",
            street: selectedAddress?.strasse ?? "",
            city: selectedAddress?.ort ?? "",
            postCode: selectedAddress?.plz ?? ""
        )
    } else {
        con.addToContacts(
            lastName: klient.nachname!,
            firstName: klient.vorname!,
            mail: klient.email ?? "",
            phone1: klient.telefon1 ?? "",
            street: selectedAddress?.strasse ?? "",
            city: selectedAddress?.ort ?? "",
            postCode: selectedAddress?.plz ?? ""
        )
    }
}

我的问题:

  • 添加联系人工作正常,没有问题。
  • 更新这个联系人没有问题。
    日志中的错误:
2023-06-21 21:28:25.166437+0200 justCare 2[64058:433979] [core] Attempted to register account monitor for types client is not authorized to access: {
    "com.apple.account.CardDAV",
    "com.apple.account.Exchange",
    "com.apple.account.LDAP"
}
2023-06-21 21:28:25.166546+0200 justCare 2[64058:433979] [accounts] CNAccountCollectionUpdateWatcher 0x6000020a04c0: Store registration failed: Error Domain=com.apple.accounts Code=7 "(null)"
2023-06-21 21:28:25.166605+0200 justCare 2[64058:433979] [accounts] CNAccountCollectionUpdateWatcher 0x6000020a04c0: Update event received, but store registration failed. This event will be handled, but the behavior is undefined.
2023-06-21 21:28:25.340559+0200 justCare 2[64058:433979] [api] Attempt to read notes by an unentitled app
2023-06-21 21:28:25.343112+0200 justCare 2[64058:433979] [General] A property was not requested when contact was fetched.
2023-06-21 21:28:25.348149+0200 justCare 2[64058:433979] [General] (
    0   CoreFoundation                      0x000000019e1d3154 __exceptionPreprocess + 176
    1   libobjc.A.dylib                     0x000000019dcf24d4 objc_exception_throw + 60
    2   CoreFoundation                      0x000000019e1d2ff8 +[NSException exceptionWithName:reason:userInfo:] + 0
    3   Contacts                            0x00000001b16f23c4 -[CNMutableContact setPhoneNumbers:] + 328
    4   justCare 2                          0x0000000100a04e04 $s10justCare_213ContactsClassC13update

<details>
<summary>英文:</summary>

In my app, I collect data from clients like names, addresses, phone numbers etc. I&#39;d like to offer a button for saving and updating these data to apple&#39;s contacts app.

Therefor I wrote this class:

class ContactsClass {
func addToContacts(
lastName: String,
firstName: String,
mail: String = "",
phone1: String = "",
street: String,
city: String,
postCode: String
) {
// Create a mutable object to add to the contact
let contact = CNMutableContact()

	contact.givenName = firstName
contact.familyName = lastName
if mail != &quot;&quot; {
let homeEmail = CNLabeledValue(label: CNLabelHome, value: mail as NSString)
contact.emailAddresses = [homeEmail]
}
contact.phoneNumbers = []
if phone1 != &quot;&quot; {
contact.phoneNumbers.append(CNLabeledValue(label: CNLabelPhoneNumberMain, value: CNPhoneNumber(stringValue: phone1)))
}
let homeAddress = CNMutablePostalAddress()
homeAddress.street = street
homeAddress.city = city
homeAddress.postalCode = postCode
contact.postalAddresses = [CNLabeledValue(label: CNLabelHome, value: homeAddress)]
// Save the newly created contact
let store = CNContactStore()
let saveRequest = CNSaveRequest()
saveRequest.add(contact, toContainerWithIdentifier: gruppe)
do {
try store.execute(saveRequest)
} catch {
print(&quot;Saving contact failed, error: \(error)&quot;)
// Handle the error
}
}
func checkForExistingContact(familyName: String, givenName: String) -&gt; CNContact? {
let store = CNContactStore()
do {
let predicate = CNContact.predicateForContacts(matchingName: familyName)
let keysToFetch = [CNContactGivenNameKey, CNContactFamilyNameKey, CNContactEmailAddressesKey] as [CNKeyDescriptor]
let contacts = try store.unifiedContacts(matching: predicate, keysToFetch: keysToFetch)
for contact in contacts {
if contact.givenName == givenName {
return contact
}
}
return nil
} catch {
return nil
}
}
func updateContact(
contact: CNContact,
lastName: String,
firstName: String,
mail: String = &quot;&quot;,
phone1: String = &quot;&quot;,
street: String,
city: String,
postCode: String
) {
let mutableContact = contact.mutableCopy() as! CNMutableContact
mutableContact.givenName = firstName
mutableContact.familyName = lastName
if mail != &quot;&quot; {
let homeEmail = CNLabeledValue(label: CNLabelHome, value: mail as NSString)
mutableContact.emailAddresses = [homeEmail]
}
mutableContact.phoneNumbers = []
if phone1 != &quot;&quot; {
mutableContact.phoneNumbers.append(CNLabeledValue(label: CNLabelPhoneNumberMain, value: CNPhoneNumber(stringValue: phone1)))
}
let homeAddress = CNMutablePostalAddress()
homeAddress.street = street
homeAddress.city = city
homeAddress.postalCode = postCode
mutableContact.postalAddresses = [CNLabeledValue(label: CNLabelHome, value: homeAddress)]
// Save the updated created contact
let store = CNContactStore()
let saveRequest = CNSaveRequest()
saveRequest.update(mutableContact)
do {
try store.execute(saveRequest)
} catch {
print(&quot;Saving contact failed, error: \(error)&quot;)
// Handle the error.
}
}

}


My button calls this func
private func addToContacts() {
let con = ContactsClass()
if let contact = con.checkForExistingContact(familyName: klient.nachname!, givenName: klient.vorname!) {
con.updateContact(
contact: contact,
lastName: klient.nachname!,
firstName: klient.vorname!,
mail: klient.email ?? &quot;&quot;,
phone1: klient.telefon1 ?? &quot;&quot;,
street: selectedAddress?.strasse ?? &quot;&quot;,
city: selectedAddress?.ort ?? &quot;&quot;,
postCode: selectedAddress?.plz ?? &quot;&quot;
)
} else {
con.addToContacts(
lastName: klient.nachname!,
firstName: klient.vorname!,
mail: klient.email ?? &quot;&quot;,
phone1: klient.telefon1 ?? &quot;&quot;,
street: selectedAddress?.strasse ?? &quot;&quot;,
city: selectedAddress?.ort ?? &quot;&quot;,
postCode: selectedAddress?.plz ?? &quot;&quot;
)
}
}

My problem:
- Adding the contact works fine. No problems.
- Updating this contact doesn&#39;t.
Error in log:

2023-06-21 21:28:25.166437+0200 justCare 2[64058:433979] [core] Attempted to register account monitor for types client is not authorized to access: {(
"com.apple.account.CardDAV",
"com.apple.account.Exchange",
"com.apple.account.LDAP"
)}
2023-06-21 21:28:25.166546+0200 justCare 2[64058:433979] [accounts] CNAccountCollectionUpdateWatcher 0x6000020a04c0: Store registration failed: Error Domain=com.apple.accounts Code=7 "(null)"
2023-06-21 21:28:25.166605+0200 justCare 2[64058:433979] [accounts] CNAccountCollectionUpdateWatcher 0x6000020a04c0: Update event received, but store registration failed. This event will be handled, but the behavior is undefined.
2023-06-21 21:28:25.340559+0200 justCare 2[64058:433979] [api] Attempt to read notes by an unentitled app
2023-06-21 21:28:25.343112+0200 justCare 2[64058:433979] [General] A property was not requested when contact was fetched.
2023-06-21 21:28:25.348149+0200 justCare 2[64058:433979] [General] (
0 CoreFoundation 0x000000019e1d3154 _exceptionPreprocess + 176
1 libobjc.A.dylib 0x000000019dcf24d4 objc_exception_throw + 60
2 CoreFoundation 0x000000019e1d2ff8 +[NSException exceptionWithName:reason:userInfo:] + 0
3 Contacts 0x00000001b16f23c4 -[CNMutableContact setPhoneNumbers:] + 328
4 justCare 2 0x0000000100a04e04 $s10justCare_213ContactsClassC13updateContact7contact8lastName05firstI09birthDate4mail6phone16phone26mobile6street4city8postCode6gruppeySo9CNContactC_S2S10Foundation0L0VSgS8StF + 1752
5 justCare 2 0x0000000100e3eb64 $s10justCare_220KlientenAdressenViewV13addToContacts33_94E28232C5F5EF34661BF1E9CA92653DLLyyF + 6208
6 justCare 2 0x0000000100e3d314 $s10justCare_220KlientenAdressenViewV4bodyQrvg7SwiftUI05TupleE0VyAE0E0PAEE5sheet11isPresented9onDismiss7contentQrAE7BindingVySbG_yycSgqd__yctAeHRd__lFQOyAE6HStackVyAGyAE6SpacerV_AE6ButtonVyAiEE10labelStyleyQrqd__AE05LabelU0Rd__lFQOyAE0V0VyAE4TextVAE5ImageVG_AE08IconOnlyvU0VQo_GAiEE8disabledyQrSbFQOyA8__Qo_A10_SgAiEE5alert_AK7actionsQrAE18LocalizedStringKeyV_APqd__yXEtAeHRd__lFQOyA10__AGyAWyA1_G_A16_tGQo_AiEE5frame5width6height9alignmentQr12CoreGraphics7CGFloatVSg_A26_AE9AlignmentVtFQOyAE7DividerV_Qo_AiEE4helpyQrA15_FQOyA10__Qo_tGG_AA014AdresseAddEditE0VQo__AiEE0M6Change2of7performQrqd___yqd__ctSQRd__lFQOyAiEEA19_A20_A21_A22_QrA26__A26_A28_tFQOyAE4ListVyAA0cD0CAE7ForEachVyAE14FetchedResultsVyA45_G10Foundation4UUIDVSgAiEE20listRowSeparatorTint_5edgesQrAE5ColorVSg_AE12VerticalEdgeO3SetVtFQOyAiEE16listRowSeparator_A56_QrAE10VisibilityO_A63_tFQOyAiEE7paddingyQrAE4EdgeOA62_V_A26_tFQOyAiEE3tagyQrqd__SHRd__lFQOyASyAGyAiEEA19_A20_A21_A22_QrA26__A26_A28_tFQOyAE6VStackVyAGyAiEEA19_A20_A21_A22_QrA26__A26_A28_tFQOyA1__Qo_Sg_A74_A74_tGG_Qo__A73_yAGyASyAGyA1__AuiEE15foregroundColoryQrA59_FQOyA3__Qo_A80_SgA3_SgtGG_ASyAGyA1__AUA1_SgA85_tGGtGGtGG_A45_Qo__Qo__Qo__Qo_GG_Qo__AA0C0CQo_tGyXEfU_A34_yXEfU_yycfU8
+ 36
7 SwiftUI 0x00000001c6e285e4 block_destroy_helper + 1276
8 SwiftUI 0x00000001c6e26978 OUTLINED_FUNCTION_1 + 23992
9 SwiftUI 0x00000001c6e269dc OUTLINED_FUNCTION_1 + 24092
10 AppKit 0x00000001a15218a8 -[NSApplication(NSResponder) sendAction:to:from:] + 440
11 AppKit 0x00000001a15216c0 -[NSControl sendAction:to:] + 72
12 AppKit 0x00000001a1521604 __26-[NSCell _sendActionFrom:]_block_invoke + 100
13 AppKit 0x00000001a152152c -[NSCell _sendActionFrom:] + 204
14 AppKit 0x00000001a1521450 -[NSButtonCell _sendActionFrom:] + 88
15 AppKit 0x00000001a151ea54 NSControlTrackMouse + 1480
16 AppKit 0x00000001a151e460 -[NSCell trackMouse:inRect:ofView:untilMouseUp:] + 144
17 AppKit 0x00000001a151e318 -[NSButtonCell trackMouse:inRect:ofView:untilMouseUp:] + 488
18 AppKit 0x00000001a151d7e4 -[NSControl mouseDown:] + 448
19 AppKit 0x00000001a151c2cc -[NSWindow(NSEventRouting) _handleMouseDownEvent:isDelayedEvent:] + 3476
20 AppKit 0x00000001a14a6f08 -[NSWindow(NSEventRouting) _reallySendEvent:isDelayedEvent:] + 364
21 AppKit 0x00000001a14a6bc8 -[NSWindow(NSEventRouting) sendEvent:] + 284
22 AppKit 0x00000001a14a5f0c -[NSApplication(NSEvent) sendEvent:] + 1556
23 AppKit 0x00000001a16f5fc4 -[NSApplication _handleEvent:] + 60
24 AppKit 0x00000001a136d368 -[NSApplication run] + 500
25 AppKit 0x00000001a1344794 NSApplicationMain + 880
26 SwiftUI 0x00000001c643f6b8 OUTLINED_FUNCTION_8 + 8272
27 SwiftUI 0x00000001c75a05ac OUTLINED_FUNCTION_14 + 188
28 SwiftUI 0x00000001c6e20c48 OUTLINED_FUNCTION_1 + 136
29 justCare 2 0x0000000101365e9c $s10justCare_20aB5_2AppV5$mainyyFZ + 40
30 justCare 2 0x000000010136619c main + 12
31 dyld 0x000000019dd23f28 start + 2236
)


Why isn&#39;t the contact updated? I would be very thankful for help.
</details>
# 答案1
**得分**: 1
错误似乎出现在根据堆栈跟踪修改联系人的电话号码部分。
>3   Contacts                            0x00000001b16f23c4 -[CNMutableContact setPhoneNumbers:] + 328
还有这个消息:
>在获取联系人时未请求属性。
查看您的代码,您的 `checkForExistingContact` 方法仅获取属性 `CNContactGivenNameKey`、`CNContactFamilyNameKey` 和 `CNContactEmailAddressesKey`。电话号码键未列出。
在 [`CNMutableContact`](https://developer.apple.com/documentation/contacts/cnmutablecontact) 文档中还有这个注意事项:
>您只能修改那些从联系人数据库中检索到的属性值。在获取联系人时,您指定要从数据库中检索哪些属性。然后,联系人存储将使用这些值填充 `CNContact` 对象的属性。在创建该对象的可变副本后,您只能修改那些存在值的属性。如果尝试访问不可用的属性,则 `CNMutableContact` 对象会引发 `CNContactPropertyNotFetchedExceptionName` 异常。
您需要更新以下行:
```swift
let keysToFetch = [CNContactGivenNameKey, CNContactFamilyNameKey, CNContactEmailAddressesKey] as [CNKeyDescriptor]

以包括您在 updateContact 方法中尝试更新的所有可能的键。

英文:

The error seems to be around modifying the contact's phone number based on the stack trace.

>3 Contacts 0x00000001b16f23c4 -[CNMutableContact setPhoneNumbers:] + 328

There's also the message:

>A property was not requested when contact was fetched.

Looking at your code, your checkForExistingContact method only fetches the attributes CNContactGivenNameKey, CNContactFamilyNameKey, and CNContactEmailAddressesKey. The phone number key is not listed.

There is also this note in the documentation for CNMutableContact:

>You may modify only those properties whose values you fetched from the contacts database. When fetching a contact, you specify which properties you want to retrieve from the database. The contact store then populates the properties of a CNContact object with those values. After creating a mutable copy of that object, you can modify only those properties for which a value exists. If you attempt to access a property that is not available, the CNMutableContact object throws a CNContactPropertyNotFetchedExceptionName exception.

You need to update the line:

let keysToFetch = [CNContactGivenNameKey, CNContactFamilyNameKey, CNContactEmailAddressesKey] as [CNKeyDescriptor]

to include all possible keys you will try to update in your updateContact method.

huangapple
  • 本文由 发表于 2023年6月22日 03:46:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/76526659.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定