有没有一种方法可以更快地获取更新的联系人?

时间:2019-02-08 10:25:49

标签: ios swift multithreading realm cncontactstore

我正在寻找一种获取添加/删除/修改的联系人以将其发送到服务器的方法。

我使用Realm是因为它比coreData更快来保存联系人 每次刷新或用户重新进入应用程序时..我正在将Realm数据库(备份)与sim联系人进行比较,以检测是否有更改(插入-修改-删除)。.

代码运行正常 但这还不够快..

我尝试在目标C文件中使用ABAddressBookRegisterExternalChangeCallback,但它并不方便,因为仅当在后台运行应用程序时更改用户时才调用它,并且它并没有给我任何有用的信息...

我也尝试了CnContactStoredidchange通知,但这没用。

这是使用全名+电话号码作为主键以便从数据库中快速获取它的databaseRealmModel im

@objcMembers class RealmModel:Object
{
dynamic var fullName: String = ""
dynamic var phoneNumber: String = ""
dynamic var firstName: String = ""
dynamic var lastName: String = ""
dynamic var middleName: String = ""
dynamic var identifier: String = ""
dynamic var primaryKey :String = ""
@objc dynamic var contactImage: Data? = nil

convenience init(fullName: String, phoneNumber:  String,firstName:String,lastName:String,middleName:String,contactImage:Data?,identifier:String)
{
self.init()
self.fullName    = fullName
self.phoneNumber = phoneNumber
self.firstName = firstName
self.lastName = lastName
self.middleName = middleName
self.contactImage = contactImage
self.identifier = identifier
self.primaryKey = identifier + phoneNumber
}

override class func   primaryKey() -> String? {
    return  "primaryKey"
}

}

2)这是我在调用方法的地方

DispatchQueue.global(qos: .userInteractive).async 
{
let start = CFAbsoluteTimeGetCurrent()
Utilities.getCotacts { (added,deleted,modified)  in
let diff = CFAbsoluteTimeGetCurrent() - start
print("Realm Took \(diff) seconds")
print( "Realm Added Contacts" + String(added.count))
print("Realm deleted Contacts" + String(deleted.count))
print("Realm modified Contacts" + String(modified.count))
}

3)这是函数的实现

class func requestForAccess(completionHandler: @escaping (_       accessGranted: Bool) -> Void) {
let authorizationStatus = CNContactStore.authorizationStatus(for: CNEntityType.contacts)

switch authorizationStatus {
case .authorized:
        completionHandler(true)

case .denied, .notDetermined:
        self.contactStore.requestAccess(for: CNEntityType.contacts,     completionHandler: { (access, accessError) -> Void in
if access {
                completionHandler(access)
}
else {
                if authorizationStatus == CNAuthorizationStatus.denied {

                                completionHandler(false)

                }
            }
        })

    default:
        completionHandler(false)
    }
}






class func getCotacts(completionHandler: @escaping (_ addedcontacts: ([RealmModel]),_ deletedContacts: ([RealmModel]),_ modifiedContacts: [RealmModel]) -> Void)
{
    var addedContacts = [RealmModel]()
    var deletedContacts = [RealmModel]()
    var modifiedContacts = [RealmModel]() 
    self.requestForAccess { (approved) in
        if approved == true
        {   //getting All contacts in database


            let realm = try! Realm()
            let Arr = realm.objects(RealmModel.self)
            var initialArr  = Array.init(Arr)
            let keysToFetch = [
                CNContactFormatter.descriptorForRequiredKeys(for: .fullName),
                CNContactEmailAddressesKey,
                CNContactImageDataKey,
                CNContactPhoneNumbersKey,CNContactImageDataAvailableKey] as! [CNKeyDescriptor]

            let contactFetchRequest = CNContactFetchRequest(keysToFetch: keysToFetch)
            do {
                try! realm.write {
                    try self.contactStore.enumerateContacts(with: contactFetchRequest) {
                        contact, stop in
                        //enumerating through contact list
                        for number in contact.phoneNumbers
                        {
                                let firstName = contact.givenName
                                let lastName  = contact.familyName
                                let middleName = contact.middleName
                                let fullName = String(format: "%@%@%@%@%@", arguments: [Utilities.isStringNull(string: contact.givenName) ? "" : contact.givenName, Utilities.isStringNull(string: contact.middleName) ? "" : " ", Utilities.isStringNull(string: contact.middleName) ? "" : contact.middleName, Utilities.isStringNull(string: contact.familyName) ? "" : " ", Utilities.isStringNull(string: contact.familyName) ? "" : contact.familyName])
                                    let phoneNumber = number.value.value(forKey: "digits") as? String
                               var contactsModel = RealmModel(fullName: fullName, phoneNumber: phoneNumber!, firstName: firstName, lastName: lastName, middleName: middleName,contactImage:contact.imageData,identifier:contact.identifier)


let databaseContact = realm.object(ofType: RealmModel.self, forPrimaryKey:contactsModel.primaryKey)
 // contact doesnt exist in database  so its a new contact
  if(databaseContact == nil)  {                                                                          addedContacts.append(contactsModel)
   realm.add(contactsModel,update: false) 
   //it's new contact no need to set update true 
   }
   else
   {  // User exists in Database
   if(databaseContact?.fullName != contactsModel.fullName)
   {
   // if full name has been changed

      let indexesOfModifiedNumber =   initialArr.indices.filter({   initialArr[$0].primaryKey == contactsModel.primaryKey })
     if indexesOfModifiedNumber.count > 0
       {
                                 modifiedContacts.append(initialArr[indexesOfModifiedNumber.first!])
                                    initialArr.remove(at:indexesOfModifiedNumber.first!)
                                        databaseContact?.fullName = contactsModel.fullName
                                         }

                                    }

                                    else
                                    {   // No Change and contact is found
                                        let indexesOfModifiedNumber =   initialArr.indices.filter({ initialArr[$0].primaryKey == contactsModel.primaryKey })
                                        if (indexesOfModifiedNumber.count > 0)
                                        {
                                        initialArr.remove(at: indexesOfModifiedNumber.first!)
                                        }

                                    }
                                }






                        }



                    }
                    if initialArr.count > 0
                    {
                        // deleted Contacts
                        deletedContacts = initialArr
                        for element in deletedContacts
                        {
                            realm.delete(element)

                        }
                    }
            completionHandler(addedContacts,deletedContacts,modifiedContacts)

                }
            }


        }
        else
        {
            print("access not approved")
        }
    }



}

因为Realm的插入和获取速度更快 我没有发现它和coreData之间有太大的区别 我正在用具有6000个联系人的电话进行测试。 核心数据需要90秒才能完成,而领域需要70秒

0 个答案:

没有答案