Do you need help on a specific subject? Use the contact form (Request a blog entry) on the right hand side.

2016-06-16

NSDate, NSCalendar and NSDateComponents

The Cocoa framework provides excellent support for working with date's. But -though not too high- the learning curve is more of a step function. The following may help:

NSDate: A moment in time. Don't think of NSDate as a date because it is not. A NSDate simply represents a moment in time.

NSCalendar: This is mental abstraction of time. Humans like to think of time in a certain way. The most common being the gregorian calendar. I.e. year, month, day, starting the year at January the 1st and ending it on December the 31st.

In our code we often need a "moment in time", i.e. an NSDate. A computer does not need mental abstractions and thus works with an internal representation of time. Which one is usually not all that important. Suffice to say that NSDate is such an internal representation. It does not matter where you are -or where your users are- the NSDate is the same for all of us.

However as soon as user interaction is needed we must convert to and from the mental abstraction of time that the user uses. For that we need to convert the NSDate to a year, month and day. Enter NSDateComponents.

NSDateComponents is a container for units that the user knows and understands: Year, month, day (and more). And to be sure, not just the end user, also the programmer ;-)

To convert a NSDate into its NSDateComponents we need a NSCalendar. You can see quite some code out there that uses a NSDateFormatter for this, but don't do that. Its cumbersome and the code is usually not that pretty or maintainable. And that is on top of conversion problems between calendars that could easily result in your code not being portable between calendar regions.

The class NSCalendar offers us a "currentCalendar" that is set to the user's preferences. This is usually the easiest way to be sure that the user will understand the GUI representation of a NSDate.

Lets take an easy example:

let now = NSDate() // Fix a moment in time
let calendar = NSCalendar.currentCalendar() // A reference to the calendar the user wants to use
let components = calendar.components(NSCalendarUnit(arrayLiteral: .Year, .Month, .Day), fromDate: now)


print("The numerical representation of now is \(components.year)-\(components.month)-\(components.day)")

Which outputs for the time of writing:

The numerical representation of now is 2016-6-16

Of course if we really wanted to create a user readable string, we could use a NSDateFormatter instead. However if we wanted to store an internal representation of the moment-in-time "now" it is much more efficient to use the "components" than do some magic around NSDateFormatter.

In a previous post I created a WallclockTime class. I did in fact also create a YearMonthDay class for my project. However I have seen the error in my way's and no longer use these. Instead I now use NSDateComponents where I need to associate a moment-in-time with user data or activities.

This results in some extensions to NSDate and NSDateComponents:

extension NSDate {
    
    func yearMonthDay(calendar: NSCalendar? = nil) -> NSDateComponents {
        let calendar = calendar ?? NSCalendar.currentCalendar()
        let components = calendar.components(NSCalendarUnit(arrayLiteral: .Year, .Month, .Day), fromDate: self)
        return components
    }
    
    func hourMinuteSecond(calendar: NSCalendar? = nil) -> NSDateComponents {
        let calendar = calendar ?? NSCalendar.currentCalendar()
        let components = calendar.components(NSCalendarUnit(arrayLiteral: .Hour, .Minute, .Second), fromDate: self)
        return components
    }
}

extension NSDateComponents {
    
    var json: VJson {
        let j = VJson.createObject(name: nil)
        if self.year != NSDateComponentUndefined { j["Year"].integerValue = self.year }
        if self.month != NSDateComponentUndefined { j["Month"].integerValue = self.month }
        if self.day != NSDateComponentUndefined { j["Day"].integerValue = self.day }
        if self.hour != NSDateComponentUndefined { j["Hour"].integerValue = self.hour }
        if self.minute != NSDateComponentUndefined { j["Minute"].integerValue = self.minute }
        if self.second != NSDateComponentUndefined { j["Second"].integerValue = self.second }
        return j
    }

    convenience init?(json: VJson?) {
        guard let json = json else { return nil }
        self.init()
        if let jval = (json|"Year")?.integerValue { self.year = jval }
        if let jval = (json|"Month")?.integerValue { self.month = jval }
        if let jval = (json|"Day")?.integerValue { self.day = jval }
        if let jval = (json|"Hour")?.integerValue { self.hour = jval }
        if let jval = (json|"Minute")?.integerValue { self.minute = jval }
        if let jval = (json|"Second")?.integerValue { self.second = jval }
    }

}

Do note that the calendar is not set on the convenience init. Hence the resulting NSDateComponents object is useful for little else than simply storage and usage in calendar operations.

This highlights an important restriction of NSDateComponents: it is a rather 'passive' class. It provides storage and does little else. Once it has been created the contents is pretty much static, even adding a calendar to it later does not change this. Once a component is set it stay's that way until we ourself set it to a suitable value.

PS: VJson is a class that you can find in SwifterJSON (on the right hand side)

Happy coding...

Did this help?, then please help out a small independent.
If you decide that you want to make a small donation, you can do so by clicking this
link: a cup of coffee ($2) or use the popup on the right hand side for different amounts.
Payments will be processed by PayPal, receiver will be sales at balancingrock dot nl
Bitcoins will be gladly accepted at: 1GacSREBxPy1yskLMc9de2nofNv2SNdwqH

We don't get the world we wish for... we get the world we pay for.

2016-06-07

Swift Code Library: 24h Wallclock Time in Swift

PS: I no longer use this class. I found that it is more convenient to stick with NSDateComponents. If I define some extensions for NSDate and NSDateComponents as in this post.

PPS: Dispatch now defines DispatchWallTime, maybe that will be enough for your needs.

While NSDateComponents is ok I find myself often needing something simpler: wouldn't it be nice to have a 24h "wallclock" time?

I finally took the (not-too-deep) plunge and defined it:

/// A 24-hour wallclock implementation
public struct WallclockTime {
    public let hour: Int
    public let minute: Int
    public let second: Int
}

There, that was not too difficult?

The wall clock time is not about accuracy, but about ease of use. Hence no sub-seconds, no days, no time-zones etc.

But to become really useful it does need some additional functions, for example comparing wall clock times to one another:

public func == (lhs: WallclockTime, rhs: WallclockTime) -> Bool {
    if lhs.hour != rhs.hour { return false }
    if lhs.minute != rhs.minute { return false }
    if lhs.second != rhs.second { return false }
    return true
}

public func != (lhs: WallclockTime, rhs: WallclockTime) -> Bool {
    return !(lhs == rhs)
}

public func > (lhs: WallclockTime, rhs: WallclockTime) -> Bool {
    if lhs.hour < rhs.hour { return false }
    if lhs.hour > rhs.hour { return true }
    // lhs.hour == rhs.hour
    if lhs.minute < rhs.minute { return false }
    if lhs.minute > rhs.minute { return true }
    // lhs.minute == rhs.minute
    if lhs.second < rhs.second { return false }
    if lhs.second > rhs.second { return true }
    // lhs.second == rhs.second
    return false
}

public func < (lhs: WallclockTime, rhs: WallclockTime) -> Bool {
    if lhs == rhs { return false }
    return !(lhs > rhs)
}

public func >= (lhs: WallclockTime, rhs: WallclockTime) -> Bool {
    if lhs == rhs { return true }
    return (lhs > rhs)
}

public func <= (lhs: WallclockTime, rhs: WallclockTime) -> Bool {
    if lhs == rhs { return true }
    return (lhs < rhs)

}

And then there is adding wall clock times to each other as well as to an NSDate:

public func + (lhs: WallclockTime, rhs: WallclockTime) -> (time: WallclockTime, tomorrow: Bool) {
    var seconds = lhs.second + rhs.second
    var minutes = lhs.minute + rhs.minute
    var hours = lhs.hour + rhs.hour
    if seconds > 59 { seconds -= 60; minutes += 1 }
    if minutes > 59 { minutes -= 60; hours += 1 }
    if hours < 24 {
        return (WallclockTime(hour: hours, minute: minutes, second: seconds), false)
    } else {
        return (WallclockTime(hour: (hours - 24), minute: minutes, second: seconds), true)
    }
}

public func + (lhs: NSDate, rhs: WallclockTime) -> NSDate {
    return NSCalendar.currentCalendar().dateByAddingComponents(rhs.dateComponents(), toDate: lhs, options: NSCalendarOptions.MatchFirst)!

}

Whoops, seems we need to be able to convert a wall clock time to date components as well:

/// A 24-hour wallclock implementation
public struct WallclockTime {
    public let hour: Int
    public let minute: Int
    public let second: Int
    
    public var dateComponents: NSDateComponents {
        let comp = NSDateComponents()
        comp.hour = self.hour
        comp.minute = self.minute
        comp.second = self.second
        return comp
    }
}
For now, I need to top it off with an extension for NSDate to create a wall clock times:

public extension NSDate {
    
    /// The wallclock time from self in the current calendar
    public var wallclockTime: WallclockTime {
        let comp = NSCalendar.currentCalendar().components([NSCalendarUnit.Hour, NSCalendarUnit.Minute, NSCalendarUnit.Second], fromDate: self)
        return WallclockTime(hour: comp.hour, minute: comp.minute, second: comp.second)
    }
    
    /// A new NSDate set to the first future wallclock time in the current calendar
    public static func firstFutureDate(with wallclockTime: WallclockTime) -> NSDate {
        return NSCalendar.currentCalendar().nextDateAfterDate(NSDate(), matchingHour: wallclockTime.hour, minute: wallclockTime.minute, second: wallclockTime.second, options: NSCalendarOptions.MatchNextTime)!
    }
}

Happy coding...

Did this help?, then please help out a small independent.
If you decide that you want to make a small donation, you can do so by clicking this
link: a cup of coffee ($2) or use the popup on the right hand side for different amounts.
Payments will be processed by PayPal, receiver will be sales at balancingrock dot nl
Bitcoins will be gladly accepted at: 1GacSREBxPy1yskLMc9de2nofNv2SNdwqH

We don't get the world we wish for... we get the world we pay for.

2016-06-02

Shortening init parameter lists with enum's

When writing an init operation for a moderately complex class (or struct) the number of parameters can explode. Even though a lot of them will probably have decent default values.

Theory tells us that 7 should be the max, but actually, even 7 is already too much.

So, what other alternatives are there?

There are two possible approaches that are often used:

1) Before object initialization

By creating an initialization options object. This object is initialized before calling the init operation and passed as a single parameter. While this can be useful if many objects have to be instantiated it usually does not much to improve code readability.

2)  After object initialization

Provide default values and make the properties accessable from the outside. Then after the initialization of the object the properties are set to the correct values. This too does nothing to improve the readability of the code, and it can cause problems if the properties really should not be modifiable after initialization.

Swift gives us a third way: Enum's with associated values, variadic parameters and optionals.

Nothing shows this better than a small example:

 class FileLog {
    
    enum InitOption {
        case MaxFileSize(Int)
        case MaxNofFiles(Int)
        case NewFileAfterDelay(NSTimeInterval)
        case NewFileDailyAt(NSDate)
    }
    
    private var filename: String
    private var fileExtension: String
    
    private var maxFileSize: Int?
    private var maxNofFiles: Int?
    private var newFileDailyAt: NSDate?
    private var newFileAfterDelay: NSTimeInterval?
    
    init?(filename: String = "logfile", fileExtension: String = "txt", options: InitOption ...) {
        
        self.filename = filename
        self.fileExtension = fileExtension
        
        for option in options {
            switch option {
            case let .MaxFileSize(size): self.maxFileSize = size
            case let .MaxNofFiles(num): self.maxNofFiles = num
            case let .NewFileAfterDelay(delay): self.newFileAfterDelay = delay
            case let .NewFileDailyAt(time): self.newFileDailyAt = time
            }
        }
    }
}

The variadic parameter 'options' allows us to only specify those properties we want to initialize. The enum with associated values gives us a way to name the properties and their values and the optionals let us know afterwards which options the callee did want to use and which not.

An example of creating an instance:

let lf = FileLog(
    filename: "MyLog",
    fileExtension: "txt",
    options:
        .MaxFileSize(20),
        .NewFileAfterDelay(3600.0)
    )

This avoids unnecessary code and does all the initialization exactly in the place it needs to be. None of the properties that are set are visible to the outside and internally we can test easily if an option is set or not.

It goes without saying that the necessary documentation should be provided in the enum and its cases. ;-)

PS: Using key/value coding it would even be possible to replace the loop with generic code to set the optional properties, however that would be taking a good thing too far imo.

Happy coding...

Did this help?, then please help out a small independent.
If you decide that you want to make a small donation, you can do so by clicking this
link: a cup of coffee ($2) or use the popup on the right hand side for different amounts.
Payments will be processed by PayPal, receiver will be sales at balancingrock dot nl
Bitcoins will be gladly accepted at: 1GacSREBxPy1yskLMc9de2nofNv2SNdwqH

We don't get the world we wish for... we get the world we pay for.

2016-04-30

Moving a xcdatamodeld from one project to another

I have an old iOS4.2 app that I want to rebuild in Swift for iOS9. The old app used CoreData and I did not want to recreate the datamodel but simply copy it over. The main reason is that I want users of the old app to be able to preserve their data in the new app.

Wel, it turns out "simply copying" it over did not work.
There are some reports on the net that cover this topic for older versions of Xcode still using Obj-c, but none of those worked for me.

Here is what I ended up doing:

1) In Xcode create the new project
2) Exit Xcode (just to be sure)
3) In the finder go to the <name>.xcdatamodeld and right-click "Show Package Contents"
4) You should see a file <name>.xcdatamodel. Open this in a text editor that will not add formatting. (I used TextWrangler)
5) Select all and Copy
6) Go to the new project and do the same: "Show Package Contents" of <name>.xcdatamodeld, open up <name>.xcdatamodel
7) Select all and Paste (i.e. change the content of the new xcdatamodel file such that it is a copy of the old one)
8) Save the new xcdatamodel file
9) Start up Xcode again, open the new project and you should see the old data model.

Happy coding...

Did this help?, then please help out a small independent.
If you decide that you want to make a small donation, you can do so by clicking this
link: a cup of coffee ($2) or use the popup on the right hand side for different amounts.
Payments will be processed by PayPal, receiver will be sales at balancingrock dot nl
Bitcoins will be gladly accepted at: 1GacSREBxPy1yskLMc9de2nofNv2SNdwqH

We don't get the world we wish for... we get the world we pay for.

2016-04-27

Replacing UIAlertView with UIAlertController

Now that I am taking a short break from OS-X programming to do some iOS development one of the first things that I encounter is the replacement of UIAlertView by UIAlertController.

Not to difficult, and I actually like the new way much better than the old.

This was the old code (still in Obj-C):

    UIAlertView *av = [[[UIAlertView alloc]
        initWithTitle:@"Error"
        message:@"Oopsie daisy"
        delegate:nil
        cancelButtonTitle:@"OK"
        otherButtonTitles:nil] autorelease];

    [av show];

This is the new code (in Swift of course):

    let alert = UIAlertController.init(
        title: "Error",
        message: "Oopsie daisy",
        preferredStyle: UIAlertControllerStyle.Alert)
      
    alert.addAction(UIAlertAction(
        title: "OK",
        style: UIAlertActionStyle.Default,
        handler: nil))

    
    presentViewController(alert, animated: true, completion: nil)

I specifically like the way action items are added to the alert view. Makes a lot of sense, and we can associate a handler (closure) with each action. It is no longer necessary to demultiplex in a single action handler.

Happy coding...

Did this help?, then please help out a small independent.
If you decide that you want to make a small donation, you can do so by clicking this
link: a cup of coffee ($2) or use the popup on the right hand side for different amounts.
Payments will be processed by PayPal, receiver will be sales at balancingrock dot nl
Bitcoins will be gladly accepted at: 1GacSREBxPy1yskLMc9de2nofNv2SNdwqH

We don't get the world we wish for... we get the world we pay for.

2016-04-24

Swift Code Library: Printing a collection type with separators in between

Sometimes I need to create a string of values from a collection type with a certain separator in between them.

An integer array would look like this: 1, 2, 3, 4
Or this: 1 - 2 - 3 - 4

Writing an operation that does this should be as universally usable as possible. The best way is to add it to the CollectionType protocol.

This was the method I ended up using:

extension CollectionType {
    
    func descriptionWithSeparator(separator: String) -> String {
        return reduce("") { $0 == "" ? "\($1)" : $0 + separator + "\($1)" }
    }
}

It was the shortest code I could come up with, but maybe not the fastest. I have not tested for speed.

Happy coding...

Did this help?, then please help out a small independent.
If you decide that you want to make a small donation, you can do so by clicking this
link: a cup of coffee ($2) or use the popup on the right hand side for different amounts.
Payments will be processed by PayPal, receiver will be sales at balancingrock dot nl
Bitcoins will be gladly accepted at: 1GacSREBxPy1yskLMc9de2nofNv2SNdwqH

We don't get the world we wish for... we get the world we pay for.

2016-04-19

Xcode Server and multiple repositories

Last week we upgraded our mac mini server such that it can now run the most recent OS.
And of course we installed OS-Server on it. A big step up from the old days of OS-X 10.7...

And of course we wanted to setup continuous integration (CI) for XCode.

But we hit a snag that cost me a good day to figure out: our first bot could not find all the necessary source files. It just so happens that we use Xcode's workspaces and in a workspace we have multiple projects:



In the project Swiftfire we use the files ASCII.swift and VJson.swift from SwifterJSON. And of course these are referenced files, i.e. Swiftfire does not have copies of those files, but refers to SwifterJSON whenever it needs the files for compilation.

That is a problem when creating bots for CI.

One of the first things a bot does is to check out the repository of its associated project. And since I created the first bot inside a project instead of the workspace it failed to check out all of the necessary files.

Inside the workspace however it is not possible to create a bot since the bot must reside in a repository for the server to check it out.

I have not found a way to create a git repository from inside Xcode when creating or working in a workspace. So I did this manually.

Note: Before doing so, it is worth noticing that git works recursive. Hence it is probably not a good idea to have a workspace repository sitting in a directory in which the projects also reside. Unless you want to tweak the '.gitignore' file. I have not tried this, but opted for the safer approach: I created a special "workspace" directory alongside the project directories:


In the workspace directory, using Xcode, I created the Q5 workspace.
Then I exited Xcode (seems safer to me) and started the Terminal. I navigated to the Workspace directory and initialised a git repository: > git init
For good measure I also added a ".gitignore" file with ".DS_Store" and "xcuserdata" in it:



At this point we may well also add and commit the files:
> git add .
> git commit -m "Initial commit"

Next I fired Xcode up again, and look, it found the workspace repository:



Using "Source Control" -> "Workspace - Master" -> "Configure Workspace" I created a new repository on the server. If you did not add & commit at the Terminal line, you need to "commit & push" the workspace file now.

One more thing to do: we now must tell Xcode which repositories are necessary when a bot is activated. This is done in the "Source Control" -> "...." -> "Configure ...." dialogue:



For each project that is needed, make sure the "include as" is checked and the popup box has selected "required".

I forgot if it is necessary at this step to perform a commit & push again. It probably is.

Anyway, you can now create bots and when executed each bot will checkout all projects and find all files necessary for its integration.


Happy coding...

Did this help?, then please help out a small independent.
If you decide that you want to make a small donation, you can do so by clicking this
link: a cup of coffee ($2) or use the popup on the right hand side for different amounts.
Payments will be processed by PayPal, receiver will be sales at balancingrock dot nl
Bitcoins will be gladly accepted at: 1GacSREBxPy1yskLMc9de2nofNv2SNdwqH

We don't get the world we wish for... we get the world we pay for.