Ошибка создания отдельного NSManagedObjectContext
Прежде чем перейти к моей проблеме, пожалуйста, посмотрите на это изображение.
Вот фактическая модель данных:
Я извлекаю набор записей из веб-API, создаю из них объекты, сохраняю их в основных данных и отображаю их в представлении «Сегодня». По умолчанию эти записи возвращаются на текущую дату.
Пользователь может нажать на кнопку «Прошлый», чтобы перейти к отдельному представлению, где он может выбрать прошлую или будущую дату из представления выбора даты и просмотреть записи для этой выбранной даты. Это означает, что мне нужно снова вызвать API, передав выбранную дату, извлечь данные, сохранить эти данные в основных данных и отобразить их. Когда пользователь покидает это представление, эти данные должны быть отброшены.
Это важная часть. Даже если я получаю новый набор данных, старые исходные данные на текущую дату в представлении «Сегодня» не должны исчезнуть. Поэтому, если / когда пользователь возвращается к представлению «Сегодня», эти данные должны быть легко доступны, так как он покинул их, и приложение не должно вызывать API и снова получать данные за текущую дату.
Я думал о создании отдельногоNSManagedObjectContext
держать эти временные данные.
У меня есть отдельный класс под названиемDatabaseManager
для решения основных задач, связанных с данными. Этот класс инициализируется с экземпляром `NSManagedObjectContext. Создает классы управляемых объектов в заданном контексте.
import CoreData
import Foundation
import MagicalRecord
import SwiftyJSON
public class DatabaseManager {
private let context: NSManagedObjectContext!
init(context: NSManagedObjectContext) {
self.context = context
}
public func insertRecords(data: AnyObject, success: () -> Void, failure: (error: NSError?) -> Void) {
let json = JSON(data)
if let records = json.array {
for recordObj in records {
let record = Record.MR_createInContext(context) as Record
record.id = recordObj["Id"].int
record.name = recordObj["Name"].string!
record.date = NSDate(string: recordObj["Date"].string!)
}
context.MR_saveToPersistentStoreAndWait()
success()
}
}
}
Так что в представлении сегодня я прохожуNSManagedObjectContext.MR_defaultContext()
вinsertRecords()
метод. У меня также есть метод для извлечения записей из данного контекста.
func fetchRecords(context: NSManagedObjectContext) -> [Record]? {
return Record.MR_findAllSortedBy("name", ascending: true, inContext: context) as? [Record]
}
Данные извлекаются из API, сохраняются в основных данных и отображаются успешно. Пока все хорошо.
В прошлом я должен делать то же самое. Но так как я не хочу, чтобы исходные данные изменились. Я попытался сделать это несколькими способами, которые предоставляет MagicalRecord.
Попытка № 1 - NSManagedObjectContext.MR_context()
Я создаю новый контекст сNSManagedObjectContext.MR_context()
, Я изменяю дату в прошлом просмотре, данные за выбранную дату успешно извлекаются и сохраняются в базе данных. Но вот в чем проблема. Когда я выбираю объекты из основных данных, я также получаю и эти старые данные. Например, каждый день имеет только 10 записей. В представлении Сегодня я отображаю 10 записей. При получении объектов в режиме «Прошлое» я получаю 20 объектов! Я предполагаю, что это старые 10 объектов плюс новые. Кроме того, когда я пытаюсь отобразить их в виде таблицы, происходит сбой сEXC_BAD_ACCESS ошибка вcellForRowAtIndexPath
метод.
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
let record = records[indexPath.row]
cell.textLabel?.text = record.name // EXC_BAD_ACCESS
cell.detailTextLabel?.text = record.date.toString()
return cell
}
Попытка № 2 - NSManagedObjectContext.MR_newMainQueueContext()
Приложение вылетает, когда я меняю дату со следующей ошибкой.
'+ entityForName: nil не является допустимым NSPersistentStoreCoordinator для поиска имени сущности' Record ''
Попытка № 3 - NSManagedObjectContext.MR_contextWithParent(NSManagedObjectContext.MR_defaultContext())
Тот же результат, что и попытка № 1.
Попытка № 4 - от ХэлаОтвет Я узнал, что, хотя я создаю два MOC, они оба относятся к одномуNSPersistentStore
, Поэтому я создал еще одно новое хранилище для хранения временных данных в моем AppDelegate.
MagicalRecord.setupCoreDataStackWithStoreNamed("Records")
MagicalRecord.setupCoreDataStackWithStoreNamed("Records-Temp")
Затем, когда я изменяю дату, чтобы получить новые данные, я устанавливаю это временное хранилище как хранилище по умолчанию, как это.
func getDate(date: NSDate) {
let url = NSPersistentStore.MR_urlForStoreName("Records-Temp")
let store = NSPersistentStore(persistentStoreCoordinator: NSPersistentStoreCoordinator.MR_defaultStoreCoordinator(), configurationName: nil, URL: url, options: nil)
NSPersistentStore.MR_setDefaultPersistentStore(store)
let context = NSManagedObjectContext.MR_defaultContext()
viewModel.populateDatabase(date, context: context)
}
Обратите внимание, что я использую контекст по умолчанию. Я получаю данные, но это тот же результат, что и попытка 1 и 3. Я получаю 20 записей. Они включают в себя данные как старой, так и новой даты. Если я используюNSManagedObjectContext.MR_context()
, он просто потерпит крах, как в Попытке 1.
Я также обнаружил кое-что еще. После создания магазинов в App Delegate я распечатал название магазина по умолчаниюprintln(MagicalRecord.defaultStoreName())
в сегодняшнем взгляде. Странно это не напечатало название, которое я дал магазину, который являетсядокументация, Вместо этого он показалReports.sqlite, Отчеты являются названием проекта. Weird.
Почему я также получаю старые данные? Я делаю что-то с при инициализации нового контекста?
Извините, если мой вопрос немного сбивает с толку, поэтому я загрузил демонстрационный проект на свойDropbox, Надеюсь, это поможет.
Любая помощь приветствуется.
Спасибо.