2

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

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

代码运行良好,但速度不够快..

我尝试在目标 C 文件中使用 ABAddressBookRegisterExternalChangeCallback ,但它并不方便,因为只有在应用程序处于后台时更改用户时才会调用它,并且它没有给我任何有用的东西......

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

这是数据库RealmModel,我使用全名+电话号码作为主键来快速从数据库中获取它

@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 秒才能完成,而 Realm 需要 70 秒

4

0 回答 0