iOS swift 如何知道即使应用程序被终止,是否有任何联系人已更新

标签 ios swift xcode

我看到很多对这个案例感到好奇的问题,但我仍然发布这个问题,因为许多开发人员可能也想知道这个另一个原因是没有解决方案适合我。

我使用了以下代码,但它仅在我的应用程序处于后台时才有效。但当我的应用程序被杀死并且用户更新了任何联系人的信息时,我没有收到通知。所以在这种情况下我不知道该怎么做。

我正在做什么:这是我正在尝试做的代码片段

From iOS 9 you can register your class to observe CNContactStoreDidChangeNotification

NSNotificationCenter.defaultCenter().addObserver(
self,
selector: #selector(addressBookDidChange),
name: NSNotification.Name.CNContactStoreDidChange,
object: nil)

然后:

@objc func addressBookDidChange(notification: NSNotification){     
//Handle event here...
}

我通过 here 找到了这个解决方案:

发生了什么:通过这种方式,一旦用户在应用程序处于后台时更新了他的联系人,我就能够收到我的应用程序通知。

我想要什么:我只想知道,即使我的应用程序被终止,如果用户更新了任何联系人,那么如何让我的应用程序收到更新的联系人通知?

如果您有此问题的解决方案,请提前告诉我。

UPDATE: I have seen Whatsapp doing this. Is there anyone who can tell me how Whatsapp is doing this?

最佳答案

要检查联系人是否已更改,您可以使用自定义哈希函数,因为 native 哈希函数仅检查标识符:

extension CNContact {
    var customHash : Int {
        var hasher = Hasher()

        hasher.combine(identifier)
        hasher.combine(contactType)
        hasher.combine(namePrefix)
        hasher.combine(givenName)
        hasher.combine(middleName)
        hasher.combine(familyName)
        hasher.combine(previousFamilyName)
        hasher.combine(nameSuffix)
        hasher.combine(nickname)
        hasher.combine(organizationName)
        hasher.combine(departmentName)
        hasher.combine(jobTitle)
        hasher.combine(phoneticGivenName)
        hasher.combine(phoneticMiddleName)
        hasher.combine(phoneticFamilyName)
        if #available(iOS 10.0, *) {
            hasher.combine(phoneticOrganizationName)
        }
        hasher.combine(note)
        hasher.combine(imageData)
        hasher.combine(thumbnailImageData)
        if #available(iOS 9.0, *) {
            hasher.combine(imageDataAvailable)
        }
        hasher.combine(phoneNumbers)
        hasher.combine(emailAddresses)
        hasher.combine(postalAddresses)
        hasher.combine(urlAddresses)
        hasher.combine(contactRelations)
        hasher.combine(socialProfiles)
        hasher.combine(instantMessageAddresses)
        hasher.combine(birthday)
        hasher.combine(nonGregorianBirthday)
        hasher.combine(dates)

        return hasher.finalize()
    }
}

(您可以删除不关心的字段)

然后,您必须在应用程序中保存一个字典来存储所有联系人的哈希值,构建它只需执行以下操作:

let hashedContacts = [String:Int]()

for contact in allContacts {
    hashedContacts[contact.identifier] = contact.customHash
}

您必须将其存储在文件系统上。

每当更新联系人时,您都会更新它:

hashedContacts[updatedContact.identifier] = updatedContact.customHash

然后在每次启动时,加载保存的字典,并检查差异:

for contact in allContacts {
    if contact.customHash != savedHashedValues[contact.identifier] {
        // This contact has changed since last launch 
        ...
    }
}

瞧!

编辑:

如何将 HashMap 保存在磁盘上...

var hashedContacts = ...

guard let name = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first?.appendingPathComponent("hashedContacts")
    else { return }

try? (hashedContacts as NSDictionary).write(to: name)

如何从磁盘加载 HashMap ...

guard 
    let name = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first?.appendingPathComponent("hashedContacts"),
    let loadedContacts = (try? NSDictionary(contentsOf: name, error: ())) as? [String:Int]
    else { return }

// Do whatever you want with loaded contacts...

关于iOS swift 如何知道即使应用程序被终止,是否有任何联系人已更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59626837/

相关文章:

iOS:UINavigationController 的交互式弹出手势期间导航栏的全宽自定义 titleView 闪烁

ios - 使用 AudioKit 的 AKHighPassFilter 过滤频率

ios:通过循环命名 View

ios - Rx swift : code working only first time

swift - 带有 unowned 关键字的闭包保留了我的对象

iOS Xcode 分发无法上传 App 以供审核 - 无法访问

ios - 为什么 self.view.subviews 在 vi​​ewDidLoad 中是一个空数组?

ios - iOS 8.3 中的调试 Realm

ios - 自定义维度 Swift 未显示在 Google Analytics 仪表板中

ios - 我的 Mac App 需要申请 Server Entitlement Key 吗?