Я потратил некоторое время на добавление поддержки Core Data в мое приложение для диффузии на основе Swift и Metal . Базовые данные — это структура, которая позволяет мне сохранять различные конфигурации распространения реакции, чтобы пользователь мог сохранять и перезагружать различные шаблоны.
Существует несколько обёрток для Core Data, которые упрощают его реализацию, включая Alecrim и Sugar Record , но этот пост в блоге посвящен самой платформе. Мои первые порты захода были Jameson Quave «s отличные учебники и, конечно же , Рэй Wenderlich .
Когда я впервые создавал свое приложение, я не ставил флажок «Использовать базовые данные», поэтому моей первой задачей было создание нового проекта Swift с выбранной опцией и копирование всех внутренностей нового AppDelegate в мой и обеспечение ссылки в managedObjectModel и persistentStoreCoordinator были правильными.
Следующим шагом вручную является создание модели данных, отражающей данные, которые я хочу сохранить. Это делается с помощью File → New → File и выбрать модель данных под Core Data вариантов. Xcode теперь открывает редактор, в котором можно определить схему модели. Вот скриншот того, как выглядит мой ReactionDiffusionEntity :
Как только он будет создан, мне нужен класс Swift для его зеркалирования. Это делается из Редактора → Создать NSManaged Subclass и генерирует следующий Swift:
class ReactionDiffusionEntity: NSManagedObject { @NSManaged var model: String @NSManaged var timestep: NSNumber @NSManaged var a0: NSNumber @NSManaged var a1: NSNumber @NSManaged var epsilon: NSNumber @NSManaged var delta: NSNumber @NSManaged var k1: NSNumber @NSManaged var k2: NSNumber @NSManaged var k3: NSNumber @NSManaged var f: NSNumber @NSManaged var k: NSNumber @NSManaged var du: NSNumber @NSManaged var dv: NSNumber @NSManaged var alpha: NSNumber @NSManaged var beta: NSNumber @NSManaged var gamma: NSNumber @NSManaged var imageData: NSData }
Теперь у меня есть соединение внутри
AppDelegate для доступа к платформе Core Data, модели данных и представлению модели Swift, я могу написать код для сохранения и загрузки моделей диффузии реакции.
Я добавил два новых экземпляра UIAlertAction в выпадающее меню гамбургеров в ReactionDiffusionEditor для сохранения и загрузки. Они вызывают saveModel () и loadModel () в моем главном контроллере представления .
Чтобы сохранить, мне нужно создать экземпляр ReactionDiffusionEntity в контексте Core Data, который копирует различные значения параметров из моего существующего объекта значения. Внутри init контроллера контроллера я создаю ссылку как на делегат приложения, так и на контекст:
let appDelegate: AppDelegate let managedObjectContext: NSManagedObjectContext required init(coder aDecoder: NSCoder) { appDelegate = UIApplication.sharedApplication().delegate as AppDelegate managedObjectContext = appDelegate.managedObjectContext! [...]
… а затем при сохранении я создаю новую сущность на основе моей модели
ReactionDiffusionModel :
func saveModel() { var newEntity = ReactionDiffusionEntity.createInManagedObjectContext(managedObjectContext, model: reactionDiffusionModel.model.rawValue, reactionDiffusionStruct: reactionDiffusionModel.reactionDiffusionStruct, image: self.imageView.image!) appDelegate.saveContext() }
managedObjectContext и
saveContext () оба пришли бесплатно , когда я создал новый проект с «Использовать Core Data» проверяется.
Метод createInManagedObjectContext () не только вставляет новый объект в контекст, он также содержит строки, которые отображаются между моим объектом значения и сгенерированным NSManagedObject :
newItem.timestep = reactionDiffusionStruct.timestep newItem.a0 = reactionDiffusionStruct.a0 newItem.a1 = reactionDiffusionStruct.a1 newItem.epsilon = reactionDiffusionStruct.epsilon newItem.delta = reactionDiffusionStruct.delta [...]
Вы также можете заметить, что я передал изображение представления изображения контроллера представления в createInManagedObjectContext () — используя небольшое написанное мной расширение для изменения размера изображений и UIImageJPEGRepresentation, я могу сохранить эскиз моделирования диффузии реакции в виде двоичных данных:
newItem.imageData = UIImageJPEGRepresentation(image.resizeToBoundingSquare(boundingSquareSideLength: 160.0), 0.75)
Для загрузки я использую executeFetchRequest () для заполнения массива ReactionDiffusionEntity :
func loadModel() { let fetchRequest = NSFetchRequest(entityName: "ReactionDiffusionEntity") if let fetchResults = managedObjectContext.executeFetchRequest(fetchRequest, error: nil) as? [ReactionDiffusionEntity] { // retrieved fetchResults.count records.... } }
Теперь, когда fetchResults заполнен, я передаю его в свой BrowseAndLoadController, который представлен в виде всплывающего диалога . Он содержит не более UICollectionView для отображения всех объектов внутри fetchResults.
Элемент рендерер создает UIImage версию хозяйствующего субъекта ImageData с использованием наблюдателя на его reactionDiffusionEntity собственности:
var reactionDiffusionEntity: ReactionDiffusionEntity? { didSet { if let _entity = reactionDiffusionEntity { label.text = _entity.model let thumbnail = UIImage(data: _entity.imageData as NSData) imageView.image = thumbnail } } }
Когда пользователь выбирает модель для загрузки, мне нужно сделать противоположное createInManagedObjectContext () — создать объект значения из моей сущности. Я делаю это с помощью функции класса на ReactionDiffusionEntity, которая выглядит как зеркальное отображение createInManagedObjectContext () :
class func createInstanceFromEntity(entity: ReactionDiffusionEntity) -> ReactionDiffusion! { var returnObject: ReactionDiffusion! var model: ReactionDiffusionModels = ReactionDiffusionModels(rawValue: entity.model)! switch model { case .BelousovZhabotinsky: returnObject = BelousovZhabotinsky() case .GrayScott: returnObject = GrayScott() case .FitzHughNagumo: returnObject = FitzhughNagumo() } // populate numeric params... returnObject.reactionDiffusionStruct.timestep = Float(entity.timestep) returnObject.reactionDiffusionStruct.a0 = Float(entity.a0) [...] returnObject.reactionDiffusionStruct.beta = Float(entity.beta) returnObject.reactionDiffusionStruct.gamma = Float(entity.gamma) return returnObject }
Это базовое сохранение и загрузка. Поскольку Xcode auto генерирует так много кода, Core Data — довольно простая вещь. Следующие шаги должны поддерживать удаление, редактирование и сохранение состояния между сеансами.
Весь исходный код этого проекта доступен в моем репозитории Git Hub здесь .