Я потратил некоторое время на добавление поддержки 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 здесь .

