Обработка большого списка контактов с помощью Realm - PullRequest
0 голосов
/ 01 июня 2018

Я застрял в проблеме с памятью с начала дня.Позволь мне объяснить.Я работаю с контактами в приложении VoIP, у нас есть два типа контактов: тот, у кого тоже есть приложение, и тот, у кого его нет.И мы используем Realm для управления этими контактами (и другими вещами, но эта проблема связана только с контактами).

Вот как мы это делаем:

LaunchViewController.swift:

sSelf.contactsService = RealmContactService()
sSelf.contactsService?.syncContacts { [weak self] _ in
    guard let sSelf = self else { return }
    sSelf.taskGroup.leave()
}

Затем в RealmContactService:

func syncContacts(askForPermission: Bool = false, completion: ((_ success: Bool) -> Void)? = nil) {
    cnContactStoreService.fetchContacts(shouldAskForPermission: askForPermission) { [weak self] (isSuccess, contacts) in
        if isSuccess {
            let realmContacts = contacts.map { cnContact -> RealmContact in
                if let existingContact = self?.fetchContact(withId: cnContact.identifier) {
                    self?.update(contact: existingContact, with: cnContact)
                    return existingContact
                }
                return RealmContact(from: cnContact)
            }
            self?.add(contacts: realmContacts, update: true)
            self?.update(contacts: realmContacts, completion: completion)
        } else {
            completion?(false)
        }
    }
}

private func update(contacts: [RealmContact], completion: ((_ success: Bool) -> Void)? = nil) {

    let phoneNumbers = contacts.flatMap { contact in
        return contact.phoneNumbers
        }.flatMap { phoneNumber in
            return phoneNumber.phoneNumberE164
    }

    contacts.forEach { (contact) in
        self.realm.beginWrite()
        contact.isAppContact = false
        self.add(contact: contact, update: true)
        try! self.realm.commitWrite()
    }

    APIClient.shared.matchAppPhoneNumber(phoneNumbers: phoneNumbers) { [weak self] response in
        guard let response = response else {
            self?.syncDeletedContacts(completion: completion)
            return
        }

        if let phoneNumbers = response.phoneNumberArray as? [PhoneNumber] {

            phoneNumbers.forEach { updatedNumber in
                contacts.forEach { contact in
                    contact.phoneNumbers.forEach { phoneNumber in
                        if phoneNumber.phoneNumberE164 == updatedNumber.phoneNumber {
                            self?.realm.beginWrite()
                            contact.isAppContact = true
                            phoneNumber.hasApp = true
                            phoneNumber.appAccountId = Int(updatedNumber.accountId)
                            self?.add(contact: contact, update: true)
                            try! self?.realm.commitWrite()
                        }
                    }
                }
            }
        }
        self?.syncDeletedContacts(completion: completion)
    }
}

И вотдве «чистые» функции области, которые мы используем для записи и обновления контакта:

func add(contact: RealmContact, update: Bool = false) {
    DispatchQueue.main.async {
        try! self.realm.write {
            self.realm.add(contact, update: update)
        }
    }
}

func update(contact: RealmContact, with cnContact: CNContact) {
    DispatchQueue.main.async {            
        try! self.realm.write {
            contact.update(from: cnContact)
        }
    }
}

Таким образом, у нас возникает проблема с памятью, подобная этой:

Сообщениеиз отладчика: прекращено из-за проблемы с памятью

Это происходит сбой только на iPhone 6 и ниже.Но было бы здорово не чрезмерно использовать память устройства!

Я знаю, что мы не справляемся с этим наилучшим образом, но я не могу найти жизнеспособное решение, и я хотел бы получить советы о том, какоптимизировать этот код.

Спасибо за вашу ценную помощь!

...