У меня такая проблема.
/ movies? Page = 0 & size = 20
конечная точка API, которая возвращает разбитые на страницы фильмы
Затем я хочу отобразить эти фильмы в UITableView.Так что легко сделать нумерацию страниц и загрузить следующие страницы фильмов.
Но теперь я хочу добавить функциональность кэширования CoreData и шаблон репозитория между ними.Примерно так:
MoviesRepository (для интеграции обеих указанных ниже зависимостей) MoviesDao (для доступа к базовым данным для фильмов) MoviesService (для выполнения удаленных вызовов API)
Я считаю, что для обработки базовых данных следует использовать один источникправда.Поэтому MoviesRepository -> fetchMovies (страница: 2, размер: 10) должны сделать что-то вроде этого:
- вызовите MoviesDao для получения [20,30) фильмов из CoreData
- сделать запрос наMoviesService -> getMovies (страница: 2, размер: 10)
- после получения ответа он должен вызвать что-то вроде MoviesDao -> syncMovies ([remoteMovies])
- , тогда должно быть обнаружено изменение Core Data ифильмы в табличном представлении должны быть обновлены (здесь я думаю о некотором наблюдаемом подходе RxSwift или о другом, как например, объединение фреймворка в функции, может быть, некоторые CoreData nofitications или FetchResultsController?
Но самая важная вещь здесь - это синхронизацияCoreData с удаленными данными, поскольку тем временем удаленные данные могут измениться, и страница 2 не равна странице 2 в основных данных и способах решения этой проблемы без повторной загрузки всех данных.
Вот код, который я нашел внекоторый учебник, но он заменяет все данные, а не страницы.
private func syncFilms(jsonDictionary: [[String: Any]], taskContext: NSManagedObjectContext) -> Bool {
var successfull = false
taskContext.performAndWait {
let matchingEpisodeRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Film")
let episodeIds = jsonDictionary.map { $0["episode_id"] as? Int }.compactMap { $0 }
matchingEpisodeRequest.predicate = NSPredicate(format: "episodeId in %@", argumentArray: [episodeIds])
let batchDeleteRequest = NSBatchDeleteRequest(fetchRequest: matchingEpisodeRequest)
batchDeleteRequest.resultType = .resultTypeObjectIDs
// Execute the request to de batch delete and merge the changes to viewContext, which triggers the UI update
do {
let batchDeleteResult = try taskContext.execute(batchDeleteRequest) as? NSBatchDeleteResult
if let deletedObjectIDs = batchDeleteResult?.result as? [NSManagedObjectID] {
NSManagedObjectContext.mergeChanges(fromRemoteContextSave: [NSDeletedObjectsKey: deletedObjectIDs],
into: [self.persistentContainer.viewContext])
}
} catch {
print("Error: \(error)\nCould not batch delete existing records.")
return
}
// Create new records.
for filmDictionary in jsonDictionary {
guard let film = NSEntityDescription.insertNewObject(forEntityName: "Film", into: taskContext) as? Film else {
print("Error: Failed to create a new Film object!")
return
}
do {
try film.update(with: filmDictionary)
} catch {
print("Error: \(error)\nThe quake object will be deleted.")
taskContext.delete(film)
}
}
// Save all the changes just made and reset the taskContext to free the cache.
if taskContext.hasChanges {
do {
try taskContext.save()
} catch {
print("Error: \(error)\nCould not save Core Data context.")
}
taskContext.reset() // Reset the context to clean up the cache and low the memory footprint.
}
successfull = true
}
return successfull
}
}