【问题标题】:CNContacts framework possible bug with phone identifier?CNContacts 框架可能带有电话标识符的错误?
【发布时间】:2017-10-04 17:41:46
【问题描述】:

最近我从旧的 ABAddressBook 框架切换到新的 CNContacts。在我的项目中,我将本地联系人与我自己的核心数据联系人同步。为此,我使用联系人标识符和电话标识符来同步电话号码。

但我观察到有趣的事情,当我尝试编辑联系人时,我调用了这行代码

func getContact() -> CNContact? {
        let contactStore = CNContactStore()
        guard let contactRecord = try? contactStore.unifiedContact(withIdentifier: "8222B6F1-DE99-4099-82A4-47EAB9206A94:ABPerson", keysToFetch: [CNContactViewController.descriptorForRequiredKeys()]) else {
            return nil
        }
        return contactRecord
    }

@IBAction func showContact() {

        let contactViewController = CNContactViewController(forNewContact: self.getContact())
        contactViewController.delegate = self
        contactViewController.title = "New Contact"

        let navigationController = UINavigationController(rootViewController: contactViewController)
        navigationController.navigationBar.isTranslucent = false
        self.present(navigationController, animated: true, completion: nil)
    }

func contactViewController(_ viewController: CNContactViewController, didCompleteWith contact: CNContact?) {
        let newContact = self.getContact()
        viewController.dismiss(animated: false, completion: nil)
    }

其实很简单。但是如果我在 CNContactViewController 中编辑用户照片,电话标识符将会改变,即使我没有在这个控制器中编辑电话号码。电话标识符可以像这样轻松打印:

po newContact?.phoneNumbers.first?.identifier

这确实打乱了我的同步,因为用户可能只是更改照片,但电话号码的标识符会更改,我无法知道发生了什么。如果我编辑一些其他数据,比如人名、公司等,这个标识符不会改变……即使我把手机编辑成其他值,它也会保持不变。但是由于某种原因,更改照片会完全搞砸。

有其他人观察到这一点吗?

这里是示例项目的链接以测试这个https://drive.google.com/file/d/0B9ngBRq15jSuZTBYNVJCaVJ5WGc/view?usp=sharing

编辑:我在真机上测试过这个

【问题讨论】:

    标签: ios cncontact cncontactviewcontroller


    【解决方案1】:

    我在 iPhone 8 模拟器上尝试了您的示例项目,但似乎无法重现该问题。这是我设置初始联系人照片后的输出:

    (lldb) po newContact?.phoneNumbers.first?.identifier
    ▿ Optional<String>
      - some : "E5D4EDC2-B6FC-4E86-9AF0-F6B78BAF41E5"
    
    (lldb) po oldContact?.phoneNumbers.first?.identifier
    ▿ Optional<String>
      - some : "E5D4EDC2-B6FC-4E86-9AF0-F6B78BAF41E5"
    

    在我再次点击按钮并将另一张照片设置为联系人照片后:

    (lldb) po oldContact?.phoneNumbers.first?.identifier
    ▿ Optional<String>
      - some : "E5D4EDC2-B6FC-4E86-9AF0-F6B78BAF41E5"
    
    (lldb) po newContact?.phoneNumbers.first?.identifier
    ▿ Optional<String>
      - some : "E5D4EDC2-B6FC-4E86-9AF0-F6B78BAF41E5"
    

    这些在我看来都一样。我对您的项目所做的唯一一件事就是将 getContact() 中的查找更改为我自己的联系人数据库中存在的标识符。

    【讨论】:

    • 尝试多次这样做,但在真实手机上。添加照片然后保存,删除照片然后保存,再次添加照片,果然会改变
    • 您可能得到不同结果的一个原因是,如果你们中的一个使用 iCloud,而另一个使用 Google 联系人 - 我观察到 Google 上的标识符变化方式与 iCloud 不同跨度>
    【解决方案2】:

    我上传了一个如何创建新联系人以及如何编辑它的示例

    https://drive.google.com/file/d/0B7OUqtQ1nSxjb3lFTFA5WnlGdFk/view?usp=sharing

    为了创建我正在使用的新联系人:

            let newContact = CNMutableContact()
            newContact.givenName = "Jhonny"
            newContact.nickname = "Jhonny"
            newContact.familyName = "My Family"
            newContact.phoneNumbers.append(CNLabeledValue(label: "Home", value: CNPhoneNumber(stringValue: "555-123-4567")))
    
            let contactViewController = CNContactViewController(forNewContact: newContact)
            contactViewController.delegate = self
            contactViewController.title = "New Contact"
            let navigationController = UINavigationController(rootViewController: contactViewController)
            self.present(navigationController, animated: true, completion: nil)
    

    注意这一行

    let contactViewController = CNContactViewController(forNewContact: newContact)
    

    用于编辑我正在使用的联系人:

            let contactViewController = CNContactViewController(for: contactRecord)
            contactViewController.delegate = self
            contactViewController.title = "Edit Contact"
            let navigationController = UINavigationController(rootViewController: contactViewController)
            self.present(navigationController, animated: true, completion: nil)
    

    再次注意这一行

    let contactViewController = CNContactViewController(for: contactRecord)
    

    我认为问题在于调用 CNContactViewController 的方式。创建和编辑的构造函数是不同的。 在演示中,您将在控制台日志中看到电话号码标识符保持不变,即使您编辑照片或其他任何内容。

    【讨论】:

    • 我尝试了您的项目,经过多次编辑 - 添加照片/删除照片,我设法获得了不同的标识符:**** 联系人 givenName:Jhonny 联系人昵称:0F386257-4071-4CC2-A2BE-18048F0F8F87 :ABPerson 电话号码标识符:D2F8B6D5-A2AC-4194-96F9-F915294E6445 *** 联系人 givenName:Jhonny 联系人昵称:0F386257-4071-4CC2-A2BE-18048F0F8F87:ABPerson 电话号码标识符:DB940E27-3ADC-42A2-8EB3-9DA7B0AD7 /跨度>
    • @MegaManX 我试过你说的()删除照片),你是对的,手机标识符改变了。我在 iOS 10 和 11 中对此进行了测试,但它仍在发生。我能问一下你用这些标识符做什么吗?也许还有另一种方法可以实现您所需要的。
    • 我正在使用它们与我的本地数据库同步,因为电话号码不是唯一的,即一个人的联系人帐户中可以有相同的号码。
    • 我会提交一个错误,我认为不幸的是你遇到的问题。您可能需要执行一些操作,例如读取字段中的实际数据并生成数据的哈希值并将其用作您的标识符来检测更改,而不是依赖系统提供的标识符。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多