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

2016-06-30

Binding Core Data objects to a GUI in OS-X

This example will show how to connect a TableView and an OutlineView to a managed object context containing core data objects.

This is not an introduction into Core Data, I assume that you are familiar with the basic principles behind Core Data.

This example is only intended as a starting point: i.e. it will do only the basic setup such that you can actually start experimenting with the bindings and implement the features you really need.

The window that will be created looks like this:



And the "Clients" tab will look like this:



Of course we also need a data model. This is (the relevant part of) the data model that I use:



Actually, the CDDomains and CDClients objects are entry points for my code, they are not necessary for this example. Also the CDCounter will not be used. The CDClient will be displayed in the Client tableview and the CDPathParts will be displayed in the Domains outline view.

The first thing to do is to create the window. I made a new nib file for it in which everything is contained. The layout is pretty much standard, it looks as follows (the controllers are already added!):



The things to notice in the above image are the following:

An Array Controller and a Tree Controller are used to fetch data from the data model context.
The Array Controller is used for the "Clients" tab (which contains a simple table) and the Tree Controller for the "Domains" tab (which contains an outline view).

We need to connect the Array Controller and the Tree Controller to our data model context.

The Array Controller must fetch the objects of the type "CDClient". To do so, select the Array Controller:



and then open the "Bindings Inspector":

 

Do not use the "Controller Content" but instead use the "Parameters" and create a binding to the managed object context. As you can see mine is located in the "File's Owner.data.managedObjectContext". The File's Owner is the Window Controller that loads the nib file.

Now switch to the "Attributes inspector":



and change the "Mode" from 'Class' to 'Entity Name'. For the "Entity Name" use the class name of the Core Data Model class that must be displayed. In my case this is 'CDClient' (as you can see above in the data model). I also ticked the boxes "Auto Rearrange Content" and "Prepares Content". (Now that I am writing this, I do not believe that auto-rearrange is necessary, but you will need prepares-content. Anyway you can quickly find that out yourself...)

The rest of the bindings for the table follow the standard (which I have blogged about before) and I will only show here the images that I used without further comment:





and:





Now on to the outline view. This one follows -of course- similar lines as for the array controller. First we bind the Tree Controller to our data model context:



No surprises here, its exactly the same as for the array controller. But the attributes inspector settings are different:



This is more interesting: First off, here too we specify an entity name, but this time it is CDPathPart. Again we tick off the "Prepares Content" box. However for the Clients we did not need a fetch predicate because we wanted to retrieve all Client objects. Here however I want to restrict the Path Parts to the top level path parts only. The others are displayed in the outline hierarchy (as can be seen in the first image). The path parts are connected via an optional "next" and "previous" relationship:



Only when the "previous" relationship is 'nil' is the path part a top level object. Thus the fetch predicate is simple enough: "previous = NIL".

Also note the setting for "Children" in the attributes. That is et to the "next" relationship. This ensures that when "next" is non-nil the outline view will show a disclosure triangle in front of the text.

That is all we "need to know" to be able to start experimenting. Of course the items in the outline view need to be connected to the tree controller. But -again- that is identical to the already shown connections tot the Array Controller.

As I said before, this is not an exhaustive example, it should be just enough to get you going. If not, please tell me what I missed -or what you needed. Either in the comments below or using the form on the right hand side.

Btw: this code will become part of Swiftfire@Github (look for version 0.10.6) and can be downloaded from there.

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-26

Creating a unique number for a NSManagedObject | A simple algorithm in Swift

Sometimes I want to create a unique number. There are many ways to do just that, and we probably all have our preferences for one way or the other.

Recently I needed to identify an NSManagedObject in a unique way that would persist across application invocations and that should offer high performance when used in comparisons.

That pretty much ruled out a UUID. A UUID is almost guaranteed unique, but since it is string based, comparing two UUIDs also could be slow.

A 64 bit integer compare is probably the fastest way to compare anything, so how to create a unique 64 bit integer?

Specific for the purpose in question (a NSManagedObject subclass) the question is: How many unique identifiers are necessary? In my case, a million per app run should be more than enough. Even though the app is designed to run months at a time, it is extremely unlikely that more than a couple of hundred -or maybe even a few thousand- objects will be created. So a million should be (much) more than enough.

An easy way to create a unique instance number is to create a static counter. And each time an instance is created the static counter is increased and its value copied to the unique id. However that would not persist well. To persist this number and still be unique on the next App start, we would need some extra code to read the number of the already present objects in the core data store. If there are a lot, then timing is an issue. And of course the (un)necessary code.

This can be done easier if we were to start the static counter from a value that is derived from the current moment in time. Since all those moments are different from each other, we only need to ensure that there won't be an overlap due to the number of objects created.

The following algorithm does that just nicely:

class CDCounter: NSManagedObject {

    private static var queue = dispatch_queue_create("nl.balancingrock.swiftfire.cdcounter", DISPATCH_QUEUE_SERIAL)

    private static var instanceCounter: Int64 = {
        return Int64(NSDate().timeIntervalSince1970) * 1_000_000
    }()
    
    override func awakeFromInsert() {
        
        dispatch_sync(CDCounter.queue, { [unowned self] in
            self.instanceId = CDCounter.instanceCounter
            CDCounter.instanceCounter += 1
        })
    }
}

The instance counter is created after program start once the first object is created. (It's a lazy variable) After that the value is incremented by 1 for each object created.

Btw: "instanceId" is a property defined in the core data model.

As long as less than 1 million objects are instantiated in a single app run, this approach is both efficient and easy to create.

Note that the initialisation of the property is done in "awakeFromInsert()" which is called only when an object is inserted into a context. Thus only once for each object.

Also note that the assignment and increment of the static variable is done in a dispatch call to ensure that multi-threading will not create duplicates. (Using Darwin.OSAtomicIncrement64 is not enough, we also must protect the time between the assignment and the increment.)

The queue that is used is used only for the assignment/increment operation. It is of course possible to use a different queue in your app to do this, as long as you are aware that the "sync" operation called on the queue can potentially lead to deadlocks. Keeping the queue private avoids this.

Can the Int64 handle the huge numbers? Yes. For the year 3000 the initialization value of the instanceCounter is 3.2*10^16. An Int64 can contain positive numbers up to 2^63 = 9.2*10^18. Thus there is even room to up the ante on the million objects per app-run.

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-24

Nil coalescing assignment | A nifty Swift addition

Just a little thing, but then again its the little things that can make life worth while.... especially as a programmer.

So, how often do you find yourself writing code like:

if str == nil { str = "Some text" }

Or the slightly better looking:

str = str ?? "Some text"

But I think it should be still shorter, what about:

str ??= "Some text"


Well, turns out that is quite possible in Swift with the following:

infix operator ??= {}

func ??=<T> (inout lhs: T?, rhs: T) {
    if lhs == nil { lhs = rhs }

}

Just include the above lines in your project, and you're set.

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-23

Using a datamodel with multiple targets

Recently I stumbled across a problem where I wanted to use a single datamodel for two targets.

While the first target had successfully used a datamodel, when I added the model to a second target I went through a succession of error messages:

+entityForName: could not locate an entity named 'SwiftfireStatistics.CDClients' in this model.

CoreData: warning: Unable to load class named 'Swiftfire.CDClients' for entity 'CDClients'

NSFetchRequest could not locate an NSEntityDescription for entity name 'SwiftfireStatistics.CDClients'

The problem seemed hard to pin down, and was badly reproducible. WTH was going on? While there was an answer on StackOverflow that helped, (adding @objC(<name>)) it was not satisfactory and I wanted to know what the underlying problems was.

I learned quite a bit about how a datamodel works and how namespaces are used, but in the end the solutions was as simple as unsatisfactory:

In the operations

let fetchRequest = NSFetchRequest(entityName: CDClients.className())

and

NSEntityDescription.insertNewObjectForEntityForName(CDClients.className(), inManagedObjectContext: self.managedObjectContext) as! CDClients

I was simply trying to be too clever for my own good.

The usage of CDClients.className() turned out to be the culprit. A class name has a namespace added in front. Thus the className() of a core data class CDClients in the target SwiftfireStatistics is in full "SwiftfireStatistics.CDClients".

What the core data functions really want is the class name without the preceding namespace:

let fetchRequest = NSFetchRequest(entityName: "CDClients")
NSEntityDescription.insertNewObjectForEntityForName("CDClients", inManagedObjectContext: self.managedObjectContext) as! CDClients

I don't like that, but it is the way it is. We could introduce a "name" property of type string and use that property instead, but...

Oh well, its the way it is.

Happy coding...

PS: You may also be interested in "Moving a datamodel from one project to another"

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-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.