Tôi không biết liệu câu hỏi này có đủ điều kiện để ở đây hay không, nhưng thậm chí sau rất nhiều nghiên cứu, tôi không thể tìm thấy hướng dẫn phù hợp cho câu hỏi này. Tôi hy vọng tôi nhận được câu trả lời ở đây.Ứng dụng nhắn tin iOS như Viber, Telegram, WhatsApp tìm nạp danh bạ nhanh như thế nào và hiệu quả
Tôi thấy rằng tất cả các ứng dụng nhắn tin như Viber, WhatsApp, Telegram tìm nạp địa chỉ liên hệ của người dùng và phân tích cú pháp nhanh và hiệu quả đến mức gần như bằng không. Tôi đã cố gắng để tái tạo điều đó nhưng chưa bao giờ thành công. Nó luôn luôn mất 40-60 giây thời gian tốt để phân tích 3000 địa chỉ liên lạc bằng cách chạy toàn bộ hoạt động trên các chủ đề nền. Thậm chí điều đó làm cho giao diện người dùng bị đóng băng trên các thiết bị chậm hơn như 5 và 5S. Sau khi tìm nạp địa chỉ liên lạc, tôi phải gửi chúng đến phần phụ trợ để xác định người dùng nào được đăng ký trên nền tảng mà cũng thêm vào tổng thời gian. Các ứng dụng được đề cập ở trên thực hiện điều này trong thời gian không!
Tôi rất vui nếu ai đó có thể đề xuất cách phân tích cú pháp các liên hệ theo cách hiệu quả nhất và nhanh hơn mà không chặn chủ đề chính.
Đây là mã, tôi sử dụng tại thời điểm này.
final class CNContactsService: ContactsService {
private let phoneNumberKit = PhoneNumberKit()
private var allContacts:[Contact] = []
private let contactsStore: CNContactStore
init(network:Network) {
contactsStore = CNContactStore()
self.network = network
}
func fetchContacts() {
fetchLocalContacts { (error) in
if let uError = error {
} else {
let contactsArray = self.allContacts
self.checkContacts(contacts: contactsArray, checkCompletion: { (Users) in
let nonUsers = contactsArray.filter { contact in
return !Users.contains(contact)
}
self.Users.value = Users
self.nonUsers.value = nonUsers
})
}
}
}
func fetchLocalContacts(_ completion: @escaping (NSError?) -> Void) {
switch CNContactStore.authorizationStatus(for: CNEntityType.contacts) {
case CNAuthorizationStatus.denied, CNAuthorizationStatus.restricted:
//User has denied the current app to access the contacts.
self.displayNoAccessMsg()
case CNAuthorizationStatus.notDetermined:
//This case means the user is prompted for the first time for allowing contacts
contactsStore.requestAccess(for: CNEntityType.contacts, completionHandler: { (granted, error) -> Void in
//At this point an alert is provided to the user to provide access to contacts. This will get invoked if a user responds to the alert
if (!granted){
DispatchQueue.main.async(execute: {() -> Void in
completion(error as! NSError)
})
} else{
self.fetchLocalContacts(completion)
}
})
case CNAuthorizationStatus.authorized:
//Authorization granted by user for this app.
var contactsArray = [EPContact]()
let contactFetchRequest = CNContactFetchRequest(keysToFetch: allowedContactKeys)
do {
// let phoneNumberKit = PhoneNumberKit()
try self.contactsStore.enumerateContacts(with: contactFetchRequest, usingBlock: { (contact, stop) -> Void in
//Ordering contacts based on alphabets in firstname
if let contactItem = self.contactFrom(contact: contact) {
contactsArray.append(contactItem)
}
})
self.allContacts = contactsArray
completion(nil)
} catch let error as NSError {
print(error.localizedDescription)
completion(error)
}
}
}
private var allowedContactKeys: [CNKeyDescriptor]{
//We have to provide only the keys which we have to access. We should avoid unnecessary keys when fetching the contact. Reducing the keys means faster the access.
return [
CNContactGivenNameKey as CNKeyDescriptor,
CNContactFamilyNameKey as CNKeyDescriptor,
CNContactOrganizationNameKey as CNKeyDescriptor,
CNContactThumbnailImageDataKey as CNKeyDescriptor,
CNContactPhoneNumbersKey as CNKeyDescriptor,
]
}
private func checkUsers(contacts:[Contact],checkCompletion:@escaping ([Contact])->Void) {
let phoneNumbers = contacts.flatMap{$0.phoneNumbers}
if phoneNumbers.isEmpty {
checkCompletion([])
return
}
network.request(.registeredContacts(numbers: phoneNumbersList), completion: { (result) in
switch result {
case .success(let response):
do {
let profiles = try response.map([Profile].self)
let contacts = profiles.map{ CNContactsService.contactFrom(profile: $0) }
checkCompletion(contacts)
} catch {
checkCompletion([])
}
case .failure:
checkCompletion([])
}
})
}
static func contactFrom(profile:Profile) -> Contact {
let firstName = ""
let lastName = ""
let company = ""
var displayName = ""
if let fullName = profile.fullName {
displayName = fullName
} else {
displayName = profile.nickName ?? ""
}
let numbers = [profile.phone!]
if displayName.isEmpty {
displayName = profile.phone!
}
let contactId = String(profile.id)
return Contact(firstName: firstName,
lastName: lastName,
company: company,
displayName: displayName,
thumbnailProfileImage: nil,
contactId: contactId,
phoneNumbers: numbers,
profile: profile)
}
private func parsePhoneNumber(_ number: String) -> String? {
do {
let phoneNumber = try phoneNumberKit.parse(number)
return phoneNumberKit.format(phoneNumber, toType: .e164)
} catch {
return nil
}
}
}`
Và các điểm tiếp xúc được lấy ở đây khi ứng dụng được khởi động
private func ApplicationLaunched() {
DispatchQueue.global(qos: .background).async {
let contactsService:ContactsService = self.serviceHolder.get()
contactsService.fetchContacts()
}
Chỉ là một câu hỏi, bạn đã thử chơi với 'allowContactKeys' chưa? Có lẽ 'CNContactThumbnailImageDataKey' quá nặng đối với 3000 địa chỉ liên lạc? Tôi không bao giờ thử nó cho nhiều địa chỉ liên lạc, nhưng tôi lấy 200 địa chỉ liên lạc gần như ngay lập tức trong ứng dụng của tôi, nhưng tôi không yêu cầu hình ảnh thu nhỏ. – TawaNicolas
Bạn đã thử tìm nạp chúng theo lô chưa? – swift2geek
Không chắc chắn nhưng tôi nghĩ WhatsApp đang bắt đầu đồng bộ hóa danh bạ ngay khi mở ứng dụng lần đầu tiên. Đọc https://www.quora.com/How-does-the-contacts-sync-work-in-WhatsApp/answer/Jinesh-Soni?srid=RhqE –