DZone
Java Zone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
  • Refcardz
  • Trend Reports
  • Webinars
  • Zones
  • |
    • Agile
    • AI
    • Big Data
    • Cloud
    • Database
    • DevOps
    • Integration
    • IoT
    • Java
    • Microservices
    • Open Source
    • Performance
    • Security
    • Web Dev
DZone > Java Zone > Swift and Core Data: Saving Data with Thumbnail Previews

Swift and Core Data: Saving Data with Thumbnail Previews

Simon Gladman user avatar by
Simon Gladman
·
Nov. 04, 14 · Java Zone · Interview
Like (0)
Save
Tweet
8.87K Views

Join the DZone community and get the full member experience.

Join For Free

I've spent some time adding Core Data support to my Swift and Metal based reaction diffusion application. Core Data is a framework that allows me to persist different reaction diffusion configurations so that the user can save and reload different patterns.

There are several wrappers to Core Data that simplify its implementation including Alecrim and Sugar Record, but this blog post looks at the framework itself. My first ports of call were Jameson Quave's excellent tutorials and, of course, Ray Wenderlich.

When I first built my application, I'd omitted to check the 'Use Core Data' checkbox, so my first task was to create a new Swift project with that option checked and copy all the guts of the new AppDelegate into mine and ensuring the references in managedObjectModel and persistentStoreCoordinator were correct.

The next manual step is to create a data model that reflects the data I want to persist. This is done via File → New → File and selecting Data Model under the Core Data options. Xcode now opens an editor where the model schema can be defined. Here's a screen grab of how my ReactionDiffusionEntity looks:

Once that's been created, I need a Swift class to mirror it. This is done from Editor → Create NSManaged Subclass and generates the following 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
            }
Now I have the plumbing inside AppDelegate to access the Core Data framework, the data model and a Swift representation of the model, I can write code to save and load reaction diffusion models. 

I've added two new UIAlertAction instances to the drop down hamburger menu in the ReactionDiffusionEditor for saving and loading. These invoke saveModel() and loadModel() in my main view controller. 

To save, I need to create an instance of ReactionDiffusionEntity in the Core Data context that copies the different parameter values from my existing value object.  Inside the view controller's init(), I create a reference to both the application delegate and the context:

 let appDelegate: AppDelegate
    let managedObjectContext: NSManagedObjectContext

    required init(coder aDecoder: NSCoder)
    {
        appDelegate = UIApplication.sharedApplication().delegate as AppDelegate

        managedObjectContext = appDelegate.managedObjectContext!
        [...]
...and then in save I create the new entity based on my model, reactionDiffusionModel:
  func saveModel()
    {
        var newEntity = ReactionDiffusionEntity.createInManagedObjectContext(managedObjectContext, model: reactionDiffusionModel.model.rawValue, reactionDiffusionStruct: reactionDiffusionModel.reactionDiffusionStruct, image: self.imageView.image!)
        
       appDelegate.saveContext()

    }
managedObjectContext and saveContext() both came for free when I created a new project with 'Use Core Data' checked.

The createInManagedObjectContext() method not only inserts a new object into the context, it also contains lines that map between my value object and the generated NSManagedObject:

newItem.timestep = reactionDiffusionStruct.timestep
        newItem.a0 = reactionDiffusionStruct.a0
        newItem.a1 = reactionDiffusionStruct.a1
        newItem.epsilon = reactionDiffusionStruct.epsilon
        newItem.delta = reactionDiffusionStruct.delta
        [...]

You may also notice that I passed the view controller's image view's image into createInManagedObjectContext() - by using a little extension I wrote to resize images and UIImageJPEGRepresentation, I'm able to save a thumbnail of the reaction diffusion simulation as binary data:

newItem.imageData = UIImageJPEGRepresentation(image.resizeToBoundingSquare(boundingSquareSideLength: 160.0), 0.75)

To load, I use executeFetchRequest() to populate an array of ReactionDiffusionEntity:

     func loadModel()
    {
        let fetchRequest = NSFetchRequest(entityName: "ReactionDiffusionEntity")
        
        if let fetchResults = managedObjectContext.executeFetchRequest(fetchRequest, error: nil) as? [ReactionDiffusionEntity]
        {
            // retrieved fetchResults.count records....
        }

    }

 

Now that fetchResults is populated, I pass that into my BrowseAndLoadController which is presented as a popover dialog. This contains not more than a UICollectionView to display all the entities inside fetchResults. 

The item renderer creates a UIImage version of the entity's imageData using an observer on its reactionDiffusionEntity property:

var reactionDiffusionEntity: ReactionDiffusionEntity?
    {
        didSet
        {
            if let _entity = reactionDiffusionEntity
            {
                label.text = _entity.model
            
                let thumbnail = UIImage(data: _entity.imageData as NSData)
            
                imageView.image = thumbnail
            }
        }

    }

When the user selects a model to load, I need to do the opposite of createInManagedObjectContext() - that is create a value object from my entity. I do this with a class function on ReactionDiffusionEntity which looks like a mirror image of 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

    }
That's the basic saving and loading done. Because Xcode auto generates so much code, Core Data is pretty simple stuff. The next steps are to support deleting, editing and persisting state between sessions.

All the source code for this project is available at my Git Hub repository here.

Core Data Data (computing) Swift (programming language)

Published at DZone with permission of Simon Gladman, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • A Guide to Events in Vue
  • Toying With Kotlin’s Context Receivers
  • Usage of Java Streams and Lambdas in Selenium WebDriver
  • What Is ERP Testing? - A Brief Guide

Comments

Java Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • MVB Program
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends:

DZone.com is powered by 

AnswerHub logo