Reputation: 333
I am using following code to load contacts from phonebook but in some iPhone devices it loads very slow. Even contacts are loading in background thread. In some devices it loads contacts quickly but in some devices its too slow.
How can i solve this issue?
//calling method to return contacts
DispatchQueue.global(qos: .background).async {
self.contacts = self.returnContacts(searchBy: nil)
DispatchQueue.main.async {
self.tblView.reloadData()
}
}
//method to return contacts
func returnContacts(searchBy:String?) -> NSArray {
let status = CNContactStore.authorizationStatus(for: .contacts)
if (status == .denied || status == .restricted) {
DispatchQueue.main.async {
let alertController = UIAlertController(title: "", message: "This app previously was refused permissions to contacts. Please go to settings and grant permission to this app so it can use contacts", preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self.present(alertController, animated: true, completion: nil)
}
return NSArray()
}
let contactStore = CNContactStore()
let keysToFetch = [
CNContactFormatter.descriptorForRequiredKeys(for: .fullName),
CNContactPhoneNumbersKey] as [Any]
// Get all the containers
var results: [CNContact] = []
do {
var allContainers: [CNContainer] = []
allContainers = try contactStore.containers(matching: nil)
// Iterate all containers and append their contacts to our results array
for container in allContainers {
let fetchPredicate = CNContact.predicateForContactsInContainer(withIdentifier: container.identifier)
do {
let containerResults = try contactStore.unifiedContacts(matching: fetchPredicate, keysToFetch: keysToFetch as! [CNKeyDescriptor])
results.append(contentsOf: containerResults)
} catch {
//print("Error fetching results for container")
}
}
// }
} catch {
// print("Error fetching containers")
}
// print(results)
results.sort{$0.givenName < $1.givenName} // sorting array by name
// Converting Array of CNContatcts into array of Dictionaries
var conatctsArr = Array<Any>()
for contactDetail in results {
var contactDic = Dictionary<String, String>()
contactDic["givenName"] = contactDetail.givenName + " " +
contactDetail.familyName
let phoneNumbers : [CNLabeledValue<CNPhoneNumber>] = contactDetail.phoneNumbers
for number in phoneNumbers {
contactDic["phoneNumber"] = number.value.stringValue
conatctsArr.append(contactDic)
}
}
// filter array
if searchBy != nil {
let predicate=NSPredicate(format: "SELF.givenName CONTAINS[cd] %@", searchBy!)
let mobileNumberpredicate = NSPredicate(format: "phoneNumber CONTAINS[cd] %@", searchBy!)
let compoundPredicate = NSCompoundPredicate.init(type: .or, subpredicates: [predicate,mobileNumberpredicate])
let arr = (conatctsArr as NSArray).filtered(using: compoundPredicate) as NSArray
conatctsArr = arr as! Array<Any>
}
///////////////////////////
//Arranging array of contatcts in sections
let finalArr = NSMutableArray()
for contactDetail in conatctsArr {
var contactDic = Dictionary<String, String>()
contactDic = contactDetail as! Dictionary
let name = contactDic["givenName"] ?? ""// Getting First character of name
var key = String()
if name.characters.count > 0 {
let index1 = name.index((name.startIndex), offsetBy: 1)
key = name.substring(to: index1)
}
else {
key = ""
}
// getting all contatcts starting with particular character
let predicate=NSPredicate(format: "SELF.givenName beginswith[c] %@",key )
let filteredArr = (conatctsArr as NSArray).filtered(using: predicate)
var dic = Dictionary<String, Any>()
dic["key"] = key
dic["values"] = filteredArr
if filteredArr.count > 0 && !(finalArr.contains(dic)) {
finalArr.add(dic)
}
}
return finalArr
}
Upvotes: 0
Views: 558
Reputation: 72855
I would try a higher priority QoS level like User-initiated
. From the docs:
Background: Work that operates in the background and isn’t visible to the user, such as indexing, synchronizing, and backups. Focuses on energy efficiency.
User-initiated: Work that the user has initiated and requires immediate results, such as opening a saved document or performing an action when the user clicks something in the user interface. The work is required in order to continue user interaction. Focuses on responsiveness and performance.
I suspect in your case that on the older devices, background
tasks are being completed on a first-in, last-out basis, and are given a very low priority, resulting in a slow return of data.
Upvotes: 1