Есть ли способ получить обновленные контакты быстрее? - PullRequest
0 голосов
/ 08 февраля 2019

Я ищу способ получения добавленных / удаленных / измененных контактов для отправки их на сервер.

Я использовал Realm, поскольку он быстрее, чем coreData, сохраняет контакты и при каждом обновлении, или когдапользователь повторно входит в приложение. Я сравниваю базу данных Realm (резервная копия) с контактами sim, чтобы определить, есть ли изменения (вставка - изменение - удаление) ..

код работает нормально, ноэто не достаточно быстро ..

Я пытался использовать ABAddressBookRegisterExternalChangeCallback в целевом C-файле, но это не было удобно, поскольку он вызывается только тогда, когда пользователь изменяется, когда приложение находится в фоновом режиме, и оно не 'не могу дать мне ничего полезного ...

также я попробовал уведомление CnContactStoredidchange, но оно бесполезно.

вот databaseRealmModel im, использующий полное имя + номер телефона в качестве primaryKey для быстрого извлечения его из базы данных

@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) вот реализация фуnction

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 секунд

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...