Enums for hard-coded configuration

While writing my new Stretch Timer app, I needed to set lower and upper limits for three key numbers. I had them hardcoded as numeric literals but when I wanted to change one of them, it occurred to me there must be a better way.

After doing a bit of research on enums, I found a construct that not only factors the numbers out to a single place, but also makes their use a lot more readable.

enum pickerRange {
    static let Stretch = (min: 5, max: 60)
    static let Rest = (min: 5, max: 60)
    static let Repeat = (min: 3, max: 15)

It is fairly plain from the enum declaration what is being described. It is also fairly evident what’s going on when they are referenced, too.

return pickerRange.Stretch.max - pickerRange.Stretch.min + 1

Using regular expressions in QShell

It’s pretty rare that I publish anything about my work, but given the difficulty I had in figuring out this particular problem with online research (in the end, I only found the answer by experimenting) I thought it would be useful to others if I published the solution.

One of the first problems I always encounter when searching industry standard technologies as they apply to the IBM i platform is that the name of the platform is incredibly hard to include in search terms, so I’ll helpfully mention here that this also applies if your search terms are AS/400, AS400, iSeries, System i, or i5/OS. Heck, I’ll even throw in a gratuitous eServer reference!

With that out of the way, the problem to be solved: using QShell to apply Unix text manipulation commands to a stream file, making use of the power of regular expressions. In my case I had downloaded a CSV file from a public site and needed to take care of some formatting prior to using the CPYFRMIMPF command to load it into a database file. I’d used this method before, but hit an additional snag this time around.

There were three problems to solve with the file, all of which I knew I could attack with sed. If you’re not familiar with sed, here’s a brief introduction to how I use it.

sed -e 's/find this/replace with this/'

You can probably figure out from the example what it will do. It’s a simple search and replace (the initial ‘s’ means ‘substitute’). As with most Unix commands, in this default form it will take standard input, filter it, and write the result to standard output. Later on I’ll hook those up to the files I need.

The next thing to know for this example is how regular expressions work. That’s way too deep a subject for me to cover here. If you need to learn this, I recommend having a read of parts 17 and 18 of Bart Busschots’ Taming the Terminal series. I’ll be using some basic features plus back references to capture groups. They will be deployed within the sed command.

So to the first problem. The first two fields in each record were actually numeric but provided as quoted values, so CPYFRMIMPF would treat them as strings and complain about the target fields being numeric. Also, there was a requirement to concatenate these two values (ironically, as if they were strings) as a new value at the end of each record. The goal, then, to strip the quotes and to append a new value on the end of the record. Back references to the rescue.

sed -e 's/^"([0-9]{1,3})","([0-9]{1,4})"(.*)$/\1,\2\3,\1\2/'

That looks pretty complex but if you break it down, it’s simply looking for two quoted groups of digits. (I specified the lengths but could have opted for lazy matching instead.)

But here’s the key reason I’m writing this article – as written above, the command will not work in QShell. It’s relatively common to need to escape capture parentheses thus: \(  … \) and this is indeed required in QShell. But even then it won’t work. The trick that took me a good hour of experimenting to discover is that QShell also requires the cardinality braces { } to be escaped! I’ve not seen this on any other platform. Here’s what actually works.

sed -e 's/^"\([0-9]\{1,3\}\)","\([0-9]\{1,4\}\)"\(.*\)$/\1,\2\3,\1\2/'

It looks a complete mess with all the back-slashes required to escape both parentheses and braces. At least the square brackets do not need the same treatment!

With my new snag out of the way (I’d not previously used cardinality), let’s move on to the next problem in the file – the dates are presented as “2017-07-15” and we need them as an 8 digit number. So we need to strip the quotes and the hyphens.

sed -e 's/"\([0-9]\{4\}\)-\([0-9]\{2\}\)-\([0-9]\{2\}\)"/\1\2\3/g'

This is a pretty simple example, but adds the ‘g’ modifier on the end to enable it to replace all matching dates in the line, not just the first.

Finally, there were a lot of empty fields in the file and because every field was quoted and some of these needed to be treated as numeric, I decided to remove all empty quotes. Which is to say, find any adjacent pair of double-quote characters and remove them. Again, this applies as many times as it can on the line.

sed -e 's/,""/,/g'

That was a really simple one. Once I had these working on the QShell command line, it was time to wrap them up for execution in my CL program, at which point I added the input file on the front by issuing a cat command and piping it into the multi-action sed command, and finally redirecting that output to my result file. Note the doubling up of the single quotes in the sed command to allow for the overall quoting of the CMD( ) parameter string.

STRQSH CMD('cat /tmp/inputfile.csv | +
sed -e ''s/^"\([0-9]\{1,3\}\)","\([0-9]\{1,4\}\)"\(.*\)$/\1,\2\3,\1\2/'' +
-e ''s/"\([0-9]\{4\}\)-\([0-9]\{2\}\)-\([0-9]\{2\}\)"/\1\2\3/g'' +
-e ''s/,""/,/g'' > /tmp/outputfile.csv')

And there you have it! Simple!

Empty or optional arrays

I needed to be able to change the colour of my entire interface when the user tapped a button. My first design consisted of a series of labels that were easily referenced by outlets. Later I decided a Table View was a better fit – but how to retrospectively update the colours of the table cells?

Easy, I thought. I added an array of UITableViewCell to my ViewController class.

var theCells : [UITableViewCell]?

It had to be optional, I thought, because I could only add the cells as the table view was built thusly in my cellForRowAtIndexPath method.

return cell

The problem was when I later went to reference the array… it was nil! Crash!

After some noodling I suddenly got to thinking – what does .append( ) actually do for an array that doesn’t actually exist yet? Certainly it didn’t throw an error, but neither did it seem to add any elements. It kind of made sense – the array doesn’t exist yet, what do I append to?

The Apple documentation gave no real clues1 but a search eventually turned up this blog post which confirmed the optionality was indeed the issue and pointed out the rather obvious, in hindsight, solution.

Instead of an optional array, an empty array initialised right there in the declaration, thus avoiding the need to override init( ).

var cellRefs : [UITableViewCell] = []

Now the .append( ) does what I expect, the array is populated and a tap of my finger changes all the colours. Yay!

  1. A saying my father used seems once again appropriate at this juncture — “Road signs are put up by people who know where they’re going.”

Using computed properties to provide display values for stored properties

I have a model class which keeps, amongst other things, the user’s current location.

public class WorldModel : NSObject, CLLocationManagerDelegate {
    private var latitude : Double = 0.0
    private var longitude : Double = 0.0

While the location is used for internal calculations, there is also a screen where I display the current location to the user. Formatting the two values for display is easy enough, but non-trivial and worth encapsulating. I found the simplest way to encapsulate it was by creating a computed property on the model class itself.

    var latLonString : String {
        get {
            let vizLatitude = Double(abs(Int32(latitude * 100))) / 100
            let vizLongitude = Double(abs(Int32(longitude * 100))) / 100
            let latitudeDirection = latitude < 0 ? "S" : "N"
            let longitudeDirection = longitude < 0 ? "W" : "E"
            return "\(vizLatitude)\(latitudeDirection), \(vizLongitude)\(longitudeDirection)"

The first two lines inside the get method truncate to two decimal places, then I figure out the North, South, East, West bits and finally return a formatted string.

Now displaying the current latitude and longitude to the user is a simple task by referring to the new property.

currentLocation.text = myWorldModel.latLonString

While a string representation of complex data is quite common, you can go the other way, too. The same class has a property for a current hue (think red, yellow, green, turquoise, blue, pink) stored as a Double, and a complex function to determine the display brightness based on the sun’s position (thus needing your location). So… what colour should the interface use right now? Easy!

    var currentHue = 0.0
    var currentColour : UIColor {
        get {
            return UIColor(hue: CGFloat(currentHue), saturation: 1.0, brightness: CGFloat(0.5 + lightLevel() / 2), alpha: 1.0)

The currentColour computed property automatically passes me a UIColor object using the current hue and the brightness based on, ultimately, the user’s location and local time (and thus sun position).

Once again, using the computed property is simple.

let currentColour = myWorldModel.currentColour
doneButton.setTitleColor(currentColour, forState: UIControlState.Normal)
currentLocationLabel.textColor = currentColour
currentLocation.textColor = currentColour

Any time you want to make use of values that can always be derived from stored properties, consider creating a computed property to do the work.

Changing layout constraints at runtime

In the app I am currently building, I decided the square button I have in one corner looks too small on an iPad screen, but it’s OK on an iPhone screen. The button is drawn by a PaintCode style kit so resizing it, in general, wasn’t going to be a problem. But, I wondered, how could I go about the resizing?

My first attempt almost worked. I had two constraints on the button to put it 8 points from the bottom and 8 points from the left, and those had to remain. I then replaced the fixed width and height constraints with an aspect ratio constraint of 1:1 and a width constraint relating to the container view with a constant of zero and a multiplier of 0.1 to make the button 10% of the width of the screen. The greater than or equal relationship, I will admit, was experimental. But it worked. Well, it worked until I rotated the device to landscape and the button suddenly grew in size! The width in landscape is considerably larger. I couldn’t have this. The button should be sized for the device, regardless of orientation. I realised at this point it was going to take some code to “find the shortest side.” But how to apply that?

A quick foray into Stack Overflow yielded no obvious answers so I asked my own question. The answer I got was super simple.

I left the aspect ratio constraint in place and set a simple width = 32 constraint (the smallest size it will ever be, given the 320 point screen width on early iPhones). Then I Control-dragged that constraint to an IBOutlet in my ViewController. I had no idea you could do this! Then it was a simple case of calculating my desired button size in viewDidLoad( ) and updating the constraint which I now have easy access to.

let buttonWidth = 0.1 * (self.view.bounds.width < self.view.bounds.height ? self.view.bounds.width : self.view.bounds.height)
widthConstraint.constant = buttonWidth

Easy, huh?

Substrings take 2

After some time away from Xcode, I got back into it again tonight. Meanwhile, I’ve got Xcode 7 installed and am hitting some differences thanks to Swift 2.

Turns out Swift Strings have been mutable in more ways than one, as it were, in that their implementation has changed significantly. The nature of the changes is aptly described in an Apple blog post and some more details on using them can be found in the standard documentation, which has been updated.

After a little reading and some tinkering, I have updated my right(Int) function to suit.

extension String {
    func right(length : Int) -> String {
        var result = self
        if result.characters.count > length {
            let range = result.startIndex..<result.endIndex.advancedBy(0 - length)
        return result


UPDATE: The below approach does not work in Swift 2. See the newer post Substrings take 2.

I guessed I’d find a nifty article on just about any Swift topic I needed, which could be linked here. I was wrong. I came to the below conclusion because I couldn’t find any articles (easily) which answered the problem and so had to go digging deeper for myself.

The task was simple. In many languages I’ve used, the simple task of left padding a string to a fixed length has been as simple as

myPaddedString = right("000" + myString, 4)

Usually used with numbers that have been converted to strings, this neatly adds the maximum possible number of leading pad characters, and uses the substring function ‘right’ to ensure only the correct number of digits are returned.

For the life of me I could not find as simple an example of doing the same thing in Swift, nor anything like it. I eventually discovered that the Unicode-ness of Swift strings demands a rather verbose approach to counting off characters, where the above becomes

myPaddedString = myString.substringFromIndex(advance(myString.startIndex, count(myString) - 4))

Not only is it verbose, it names my source variable an astonishing three times!

But, I surmised, at the end of it all, the only input I have provided is the same two values I had in my simple assumptive statement at the top. And this is where some of Swift’s niftier features comes to the rescue – extensions.

It is quite trivial to take the above code and extend the String class.

extension String {
    func right(length : Int) -> String {
        return self.substringFromIndex(advance(self.startIndex, count(self) - length))

After which, the required statement is remarkably close to what I had expected.

myPaddedString = myString.right(2)

I get that there is complexity in Strings, but if I could write a simple extension, I wonder why Apple didn’t.

Apple’s official Swift tweets

So, after I came up with this idea, found the domain available, created the web site and tweaked it to my liking – I discover there is what appears to be an official @swifttips Twitter account from Apple.

Hopefully they don’t get upset about this little site – or maybe they’ll buy the domain for millions. I can only hope. 🙂