Tuesday, June 9, 2015

A Simple Swift iOS App from Start to Finish - Creating the Data Model's Wrapper Class

Introduction

This is part of a series of articles describing the creation of a simple iOS app. A complete list of the articles is included in the first part A Simple Swift iOS App from Start to Finish - Introduction.

I have set up a web site for the finished app at http://DaysWithoutThings.com and you can download it free directly from the app store:




In this article I am going to create the wrapper class for my Thing entity and implement the code for a calculated property called currentDayCount.


Creating the Wrapper Class

Core Data entities are accessed in code via wrapper classes. Xcode has an option to generate these wrappers. The option is accessed from the main menu's Editor submenu and is called 'Create NSManagedObject Subclass...'.

The menu is context sensitive so this option is only available when a data model is displayed in the main editor window.

Clicking the opens a window asking me to select the data models I want to generate wrappers for.



I only have one model in my project and it is already checked so I am just going to click 'Next'.

The next window asked me to select which entities, in the selected models, I would like to generate wrappers for.







My Thing entity is already selected so I am just going to click 'Next' again.

The next windows asks me where I want to save the generated class to. It also allows me to choose the programming language to use for the generated classes.





I am going to change the language from the default Objective-C to Swift and then click 'Create'.

Xcode creates a new class for each entity and flags it to be added to source control. It also flags the Data Model as modified. This is because the model tracks the classes that represent its entities. I can view this change by selecting the model's file in the Project navigator and switching the main view to Version editor.





The newly generated Swift file contains a class definition for the 'Thing' class which includes properties for each of the entities attributes.


Implementing a Calculated Property

I want my Thing class to have a property called currentDayCount that will be calculated by comparing the startDate attribute to the current Date. If I was using Objective-C I could just declare currentDayCount a  transient attribute in my data model and provide my own getter method to return its calculated value. This is not possible in Swift as it only allows the value of properties representing transient attributes to be set in the entity object's awakeFromFetch method. 
To workaround this limitation I am going to define currentDayCount as a normal property. However, as the Thing class was generated by Xcode and will need to be regenerated if I ever change anything in my data model, I do not want to define the new property in the Thing class file itself.  Instead I am going to create a Swift extension to the Thing class in a separate file.

To do this I am going to add a new Swift file to my project.


I am going to call the new file Thing+currentDayCount.swift which is the class name plus the property I will be adding. This follows the naming convention for creating a category which is the Objective-C equivalent of a Swift extension. This creates a new Swift file that just contains the import for the Swift Foundation library.
To this I am going to add the definition of my currentDayCount property.


import Foundation

let SECONDS_IN_DAY:Double = 60 * 60 * 24

extension Thing {
    
    var currentDayCount: NSNumber {
        get {
            var seconds:NSTimeInterval = -self.startDate.timeIntervalSinceNow
            var days:NSTimeInterval = seconds / SECONDS_IN_DAY
            var wholeDays:Int = Int(days)
            return wholeDays
        }
    }
    

}

This defines a constant to hold the number of seconds in a day which the getter then uses to divide the difference between the current time and date from the time and days stored in the Thing's startDate property.  It returns the result as an integer which has the effect of rounding the number down to the last whole number.


Wrapping up

My Thing class is now complete. Before moving on I am going to run my app in the Simulator to make sure it still compiles and then commit it to source control.

In my next article  I will create a class to hold a collection of my Thing entity objects.

Next:       A Simple Swift iOS App from Start to Finish - Creating the Collection Class

No comments:

Post a Comment