Как правильно выполнить постоянную очистку истории, не влияя на корректность CloudKit?IOS

Программируем под IOS
Ответить
Anonymous
 Как правильно выполнить постоянную очистку истории, не влияя на корректность CloudKit?

Сообщение Anonymous »

В настоящее время мы используем локальные CoreData с функцией CloudKit, используя NSPersistentCloudKitContainer.
Почему мы включаем функцию постоянного отслеживания истории?< /h2>
Из-за проблемы, описанной в https://stackoverflow.com/a/72554542/72437, нам необходимо включить NSPersistentHistoryTrackingKey.

Очистить историю
На основании https://developer.apple.com/documentati ... re_changes, мы должны выполнить постоянную очистку истории вручную.< /p>

Но не совсем ясно, как мы можем очистить историю безопасным способом, не влияя на корректность CloudKit. Мы обычно проводим несколько тестов со следующей настройкой.
  • Запустите симулятор. Мы выполним операцию вставки в симуляторе.
  • Запустите реальное устройство. Реальное устройство получит автоматическое push-уведомление на этапе 1.
  • И симулятор, и реальное устройство выполняют один и тот же код.
  • Каждый раз, когда мы вставьте элемент в симулятор, и мы посмотрим, что произойдет на реальном устройстве.
Тест 1: Очистка все данные истории сразу после обработки

Код: Выделить всё

@objc func storeRemoteChange(_ notification: Notification) {
// Process persistent history to merge changes from other coordinators.
historyQueue.addOperation {
self.processPersistentHistory()
}
}

/**
Process persistent history, posting any relevant transactions to the current view.
*/
private func processPersistentHistory() {
backgroundContext.performAndWait {

// Fetch history received from outside the app since the last token
let historyFetchRequest = NSPersistentHistoryTransaction.fetchRequest!
historyFetchRequest.predicate = NSPredicate(format: "author != %@", appTransactionAuthorName)
let request = NSPersistentHistoryChangeRequest.fetchHistory(after: lastHistoryToken)
request.fetchRequest = historyFetchRequest

let result = (try? backgroundContext.execute(request)) as? NSPersistentHistoryResult
guard let transactions = result?.result as? [NSPersistentHistoryTransaction] else { return }

...

// Update the history token using the last transaction.
lastHistoryToken = transactions.last!.token

// Remove history before the last history token
let purgeHistoryRequest = NSPersistentHistoryChangeRequest.deleteHistory(before: lastHistoryToken)
do {
try backgroundContext.execute(purgeHistoryRequest)
} catch {
error_log(error)
}
}
}
По нашим наблюдениям, реальное устройство получает неверную информацию о синхронизации CloudKit. Реальное устройство либо получает дублированные данные, либо его данные удаляются.
Наша гипотеза по поводу этой проблемы:
  • Данные истории персистентности распределяются между несколькими координаторами персистентности.
  • Наш видимый координатор завершил обработку транзакции, отметьте запись в LastHistoryToken, а затем очистите все истории старше, чем LastHistoryToken< /code>.
  • Однако существует еще один невидимый координатор, используемый CloudKit для синхронизации. Существует высокая вероятность того, что координатор CloudKit еще не обработал удаленные транзакции истории.
  • Это приводит к тому, что все данные становятся неправильными, когда CloudKit пытается синхронизировать данные реального устройства без необходимой истории транзакций.
Тест 2. Удаление всех данных истории старше 2 минут после обработки< /h2>
Мы настраиваем приведенный выше код, удаляя только историю транзакций старше 2 минут.

Код: Выделить всё

// Remove history older than 2 minutes.
let date = Date(timeMillis: Date.currentTimeMillis - 2*60*1000)
let purgeHistoryRequest = NSPersistentHistoryChangeRequest.deleteHistory(before: date)
do {
try backgroundContext.execute(purgeHistoryRequest)
} catch {
error_log(error)
}
Наше наблюдение заключается в том, что
  • Если разница во времени между последним срабатыванием storeRemoteChange и текущим срабатыванием storeRemoteChange< /code> меньше 2 минут, реальное устройство получит правильную информацию о синхронизации CloudKit.
  • Если разница во времени между последним срабатыванием storeRemoteChange и текущий storeRemoteChange превышает 2 минуты, реальное устройство получит неправильную информацию для синхронизации CloudKit. Реальное устройство либо получает дублированные данные, либо его данные удаляются.
Сводка и вопрос
На основе статьи «Как сократить историю прямо в приложении CoreData+CloudKit?»
Предлагает автор

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

Для 1 пользователя: Корпус для 2 устройств.
  • Пользователь часто читает/пишет на своем часто используемом устройстве A.
  • пользователь запустит то же приложение на своем редко используемом устройстве Б через 7 дней с момента последнего использования на устройстве Б.
Означает ли это, что устройство Б будет получать неверную информацию о синхронизации CloudKit? (Похоже, что да, судя по наблюдениям в Тесте 2)
Если да, то каков хороший способ выполнить постоянную очистку истории, не влияя на корректность CloudKit?

Как запустить тест 2?
Вы можете настроить и запустить тест 2
  • Настройте и запустите пример из https://developer.apple.com/documentati ... _the_cloud
  • Замените CoreDataStack.swift на https: //gist.github.com/yccheok/df21f199b81b19764ffbcd4a4583c430. Он содержит вспомогательные функции для даты и код очистки двухминутной истории.
  • В симуляторе создайте 1 записи, коснувшись верхнего правого угла. Вы можете видеть, что на реальном устройстве теперь есть 1 записей.
  • Через 3 минуты снова нажмите в правом верхнем углу. В симуляторе вы можете увидеть всего 2 записи. Однако на реальном устройстве данные исчезли!
[img]https://i.sstatic .net/I9tdR.jpg[/img]
(На этом рисунке левое устройство — настоящее устройство, а правое — симулятор)

Подробнее здесь: https://stackoverflow.com/questions/725 ... ffecting-t
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «IOS»