我正在使用以下代码从电话簿加载联系人,但在某些iPhone设备中加载非常慢。甚至联系人都在后台线程中加载。在某些设备中,它可以快速加载触点,但在某些设备中它的速度太慢。
我该如何解决这个问题?
//调用返回联系人的方法
DispatchQueue.global(qos: .background).async {
self.contacts = self.returnContacts(searchBy: nil)
DispatchQueue.main.async {
self.tblView.reloadData()
}
}
//返回联系人的方法
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
}
答案 0 :(得分:0)
我会尝试更高优先级的QoS级别,如User-initiated
。来自docs:
后台:在后台运行并且对用户不可见的工作,例如索引,同步和备份。重点关注能源效率。
用户启动:用户已启动的工作,需要立即生成结果,例如在用户点击用户界面中的内容时打开已保存的文档或执行操作。需要这项工作才能继续用户互动。重点关注响应能力和绩效。
我怀疑在您的情况下,在旧设备上,background
任务正在以先进先出的方式完成,并且优先级非常低,导致数据返回缓慢。