|
|
|
@ -15,6 +15,7 @@ class SystemContactsFetcher: NSObject {
|
|
|
|
|
|
|
|
|
|
private let TAG = "[SystemContactsFetcher]"
|
|
|
|
|
var lastContactUpdateHash: Int?
|
|
|
|
|
var lastDelegateNotificationDate: Date?
|
|
|
|
|
|
|
|
|
|
public weak var delegate: SystemContactsFetcherDelegate?
|
|
|
|
|
|
|
|
|
@ -109,7 +110,7 @@ class SystemContactsFetcher: NSObject {
|
|
|
|
|
|
|
|
|
|
systemContactsHaveBeenRequestedAtLeastOnce = true
|
|
|
|
|
|
|
|
|
|
DispatchQueue.global().async {
|
|
|
|
|
DispatchQueue.default.async {
|
|
|
|
|
var systemContacts = [CNContact]()
|
|
|
|
|
do {
|
|
|
|
|
let contactFetchRequest = CNContactFetchRequest(keysToFetch: self.allowedContactKeys)
|
|
|
|
@ -126,20 +127,46 @@ class SystemContactsFetcher: NSObject {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let contacts = systemContacts.map { Contact(systemContact: $0) }
|
|
|
|
|
|
|
|
|
|
let contactsHash = HashableArray(contacts).hashValue
|
|
|
|
|
guard (self.lastContactUpdateHash != contactsHash) else {
|
|
|
|
|
Logger.debug("\(self.TAG) System contacts unchanged. hash:\(contactsHash)")
|
|
|
|
|
|
|
|
|
|
DispatchQueue.main.async {
|
|
|
|
|
completion?(nil)
|
|
|
|
|
var shouldNotifyDelegate = false
|
|
|
|
|
|
|
|
|
|
if self.lastContactUpdateHash != contactsHash {
|
|
|
|
|
Logger.info("\(self.TAG) contact hash changed. new contactsHash: \(contactsHash)")
|
|
|
|
|
shouldNotifyDelegate = true
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
// If nothing has changed, only notify delegate (to perform contact intersection) every N hours
|
|
|
|
|
if let lastDelegateNotificationDate = self.lastDelegateNotificationDate {
|
|
|
|
|
let kDebounceInterval = TimeInterval(12 * 60 * 60)
|
|
|
|
|
|
|
|
|
|
let expiresAtDate = Date(timeInterval: kDebounceInterval, since:lastDelegateNotificationDate)
|
|
|
|
|
if Date() > expiresAtDate {
|
|
|
|
|
Logger.info("\(self.TAG) debounce interval expired at: \(expiresAtDate)")
|
|
|
|
|
shouldNotifyDelegate = true
|
|
|
|
|
} else {
|
|
|
|
|
Logger.info("\(self.TAG) ignoring since debounce interval hasn't expired")
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
Logger.info("\(self.TAG) first contact fetch. contactsHash: \(contactsHash)")
|
|
|
|
|
shouldNotifyDelegate = true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
guard shouldNotifyDelegate else {
|
|
|
|
|
Logger.info("\(self.TAG) no reason to notify delegate.")
|
|
|
|
|
|
|
|
|
|
completion?(nil)
|
|
|
|
|
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
self.lastContactUpdateHash = contactsHash
|
|
|
|
|
|
|
|
|
|
Logger.debug("\(self.TAG) Notifying delegate that system contacts did change. hash:\(contactsHash)")
|
|
|
|
|
|
|
|
|
|
DispatchQueue.main.async {
|
|
|
|
|
self.lastDelegateNotificationDate = Date()
|
|
|
|
|
self.lastContactUpdateHash = contactsHash
|
|
|
|
|
|
|
|
|
|
self.delegate?.systemContactsFetcher(self, updatedContacts: contacts)
|
|
|
|
|
completion?(nil)
|
|
|
|
|
}
|
|
|
|
|