|
|
|
@ -39,11 +39,19 @@ class SystemContactsFetcher: NSObject {
|
|
|
|
|
CNContactEmailAddressesKey as CNKeyDescriptor
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
public func requestOnce() {
|
|
|
|
|
/**
|
|
|
|
|
* Ensures we've requested access for system contacts. This can be used in multiple places,
|
|
|
|
|
* where we might need contact access, but will ensure we don't wastefully reload contacts
|
|
|
|
|
* if we have already fetched contacts.
|
|
|
|
|
*
|
|
|
|
|
* @param completion completion handler is called on main thread.
|
|
|
|
|
*/
|
|
|
|
|
public func requestOnce(completion: ((Error?) -> Void)?) {
|
|
|
|
|
AssertIsOnMainThread()
|
|
|
|
|
|
|
|
|
|
guard !systemContactsHaveBeenRequestedAtLeastOnce else {
|
|
|
|
|
Logger.debug("\(TAG) already requested system contacts")
|
|
|
|
|
completion?(nil)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
systemContactsHaveBeenRequestedAtLeastOnce = true
|
|
|
|
@ -54,22 +62,32 @@ class SystemContactsFetcher: NSObject {
|
|
|
|
|
contactStore.requestAccess(for: .contacts) { (granted, error) in
|
|
|
|
|
if let error = error {
|
|
|
|
|
Logger.error("\(self.TAG) error fetching contacts: \(error)")
|
|
|
|
|
assertionFailure()
|
|
|
|
|
DispatchQueue.main.async {
|
|
|
|
|
completion?(error)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
guard granted else {
|
|
|
|
|
Logger.info("\(self.TAG) declined contact access.")
|
|
|
|
|
// This case should have been caught be the error guard a few lines up.
|
|
|
|
|
assertionFailure()
|
|
|
|
|
DispatchQueue.main.async {
|
|
|
|
|
completion?(nil)
|
|
|
|
|
}
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DispatchQueue.main.async {
|
|
|
|
|
self.updateContacts()
|
|
|
|
|
self.updateContacts(completion: completion)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
case .authorized:
|
|
|
|
|
self.updateContacts()
|
|
|
|
|
self.updateContacts(completion: completion)
|
|
|
|
|
case .denied, .restricted:
|
|
|
|
|
Logger.debug("\(TAG) contacts were \(self.authorizationStatus)")
|
|
|
|
|
DispatchQueue.main.async {
|
|
|
|
|
completion?(nil)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -79,10 +97,10 @@ class SystemContactsFetcher: NSObject {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
updateContacts()
|
|
|
|
|
updateContacts(completion: nil)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private func updateContacts() {
|
|
|
|
|
private func updateContacts(completion: ((Error?) -> Void)?) {
|
|
|
|
|
AssertIsOnMainThread()
|
|
|
|
|
|
|
|
|
|
systemContactsHaveBeenRequestedAtLeastOnce = true
|
|
|
|
@ -100,11 +118,16 @@ class SystemContactsFetcher: NSObject {
|
|
|
|
|
} catch let error as NSError {
|
|
|
|
|
Logger.error("\(self.TAG) Failed to fetch contacts with error:\(error)")
|
|
|
|
|
assertionFailure()
|
|
|
|
|
DispatchQueue.main.async {
|
|
|
|
|
completion?(error)
|
|
|
|
|
}
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let contacts = systemContacts.map { Contact(systemContact: $0) }
|
|
|
|
|
DispatchQueue.main.async {
|
|
|
|
|
self.delegate?.systemContactsFetcher(self, updatedContacts: contacts)
|
|
|
|
|
completion?(nil)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -118,7 +141,7 @@ class SystemContactsFetcher: NSObject {
|
|
|
|
|
|
|
|
|
|
@objc
|
|
|
|
|
private func contactStoreDidChange() {
|
|
|
|
|
updateContacts()
|
|
|
|
|
updateContacts(completion: nil)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|