SwiftUI Snapshot Testing

Snapshot testing is a technique that has been very popular in the web development world and it seems like a great way to test SwiftUI user interfaces. I read about snapshot tests in a recent blog post and was intrigued, but I had some difficulty getting it to work, so when I finally succeeded, I decided to share my experiences in the hope that others will find them useful.

What is Snapshot Testing

Unit testing checks that when you call various functions or methods with certain inputs, you get the output you expect. I use unit tests for testing my models and the methods that change them. But this only tests the logic behind the app, it does nothing to test whether the app is displaying what it should, or whether it is responding correctly to the user’s actions.

UI testing emulates user actions by faking taps, clicks, text entry and so on and checks that labels, buttons etc are showing the correct information after these fake interactions.

Snapshot testing is in between these two as it effectively takes a picture of the interface. The first time you run the test it will store an image and all subsequent test runs will check that the current interface matches this stored image. If there are any differences, the test will fail so you can decide whether to keep the new version or revert to what you had before.

How did I get started?

I first read about the idea of using snapshot testing for SwiftUI in a blog post by Vadim Bulavin. He made a very good argument for this, but I found his instructions assumed more knowledge of the topic than I had at the time and so I discarded the idea after an initial attempt.

On the final pane, it is important to select the correct target for this package. Select the app’s test target, not the app itself and not the UI test target if you have one. I made this mistake on my first try as I assumed that snapshot testing would be part of UI testing but it is actually part of unit testing.

Writing a Snapshot Test

Now I added a new Unit Test Case Class file to the tests target in my app. I had to import SwiftUI and SnapshotTesting into this test file as well as declaring the app as a testable import. The easiest way to do this is to copy the @testable import heading from the sample test file to make sure it is exactly right. The import needs to match the name of your app module.

This uses the snapshot library’s assertSnapshot method to save the content view as an image. But unfortunately, this doesn’t work. The problem is that the second parameter is a Snapshotting strategy that can convert various UI elements into some form of data or image. But the library doesn’t know what a SwiftUI View is, so it needs a way to convert the view into something that can be recognized by the snapshotter.

I added this extension to SwiftUI’s View that wraps the SwiftUI View in a UIHostingController. It returns this as a UIViewController which is a valid input for a snapshotter and can be converted to an image.

And it worked. Or rather it failed as expected because there was no image to compare it with.

Checking the error message, I was able to see where it had created the snapshot image file which I could look at. And the second time I ran the test, it passed.

If you ever get an error message saying “No such module ‘SnapshotTesting’” use Shift-Command-U to re-build for testing. This usually only happens after you have cleaned your build folder.

Testing a Change

Now that I had a passing test, the next thing was to check what happens if the UI changes. This may be due to a deliberate change or because the cat just walked across your keyboard (a not infrequent occurrence around here).

Where I originally had a button with the label “Save”, I decided to change this to “OK” (rejecting the cat’s suggestion of “q2eegrnh”).

Running the test again produced this result:

And I was then able to compare the 2 images, using the path to the failing image from the error message.

Once I had confirmed that the new image was what I wanted and not a result of error, either feline or human, I set the test to record a new result so that the new version became the official test version.

This caused a failing test again as the new version was written to the Snapshots folder, but after removing the record = true line and re-running the test, it passed again, with my new button label now an accepted part of the test.

Using Snapshots with State

In SwiftUI, the UI displayed is a function of state, so changing state properties changes the UI. This is what makes snapshot testing really good for SwiftUI apps as you can change the state programmatically and confirm that this is reflected in the UI.

So having proved that the snapshot tests worked, I decided to move on and test it with my new anagram assistant app. This is quite a simple app that has a single AppState class that holds all the program data.

So I was able to write a suite of tests that changed the state in various ways and then snap-shotted the UI with that state. Here are a couple of examples:

This worked really well with only one slight problem. As the state arranges the availableLetters array randomly for display, I had to add a sort to make sure they always displayed in the same order and made the tests repeatable.

And as a bonus, I was able to test a screen in dark mode with this test which sets the colorScheme:

Accessibility Tests

iOS supports dynamic type and if your app uses standard font styles, it will adopt these dynamic sizes automatically. I can’t find the link right now, but I remember reading an article that said nearly half of all iPhone users change the default text size, setting it either smaller or larger.

With snapshot testing, it is quick and easy to get a view of how you app looks with different font sizes. Here is my test function for taking a snapshot of every possible font size variation.

I chose an arbitrary size for the snapshot, you just need to make sure your UI will fit into whatever size you select.

The real problem was with sand-boxing. The snapshot library was blocked from writing the image files to the project directory if the app was sand-boxed. This seems really peculiar, since Xcode is running the tests and Xcode writes to the project directory all the time!

I found two ways around this:

Turn off sand-box mode temporarily while testing.

Make a non-sand-boxed target and use it for testing against.

Neither of these are particularly great. Option 1 is tedious, although I think it can work if the snapshots remain the same, it only fails if there is a change that it needs to write to disk.

Option 2 is tedious to set up (contact me if you would like more details) but is more seamless after that.

The best solution would be for Xcode to allow you to turn off sand-boxing for a test target. Maybe Xcode 12…

Limitations of Snapshot Testing

Ignoring the Mac and concentrating only on iOS apps for the moment, there were a few issues:

You have to run your tests against the same simulator every time, or at least against a simulator with the same screen dimensions. I decided to to use the iPhone SE (2nd generation) as it has a small screen and I find smaller screens to be more of a problem than large ones. You also need to make sure it is always using the same appearance: light or dark, unless you want to specify this for every test.

I ended up with this setup function that ran before my snapshot test suite:

This uses a couple of tricks that are supposed to speed up tests and has a record setting that I could set for the entire suite if I wished, and it throws a fatalError if I select the wrong device or simulator.

It would be neater if Xcode allowed you to select a simulator in the test target build settings, but I think you can only do this if you run tests from the command line.

Snapshot tests confirm that the UI matches the state, but they do not check to see if the state changes in response to user input. That is the missing link that UI testing provides, but even without that, I believe that snapshot testing is a very useful tool and much better than having no form of UI testing at all.

You need to look at your snapshots. This may sound obvious but the snapshot library creates a set of images. These images are then set as the goal for future tests. If you don’t check that they are correct, then every test could be confirming that the UI is wrong but unchanged. If the tests report a difference, look at both copies and see which one is right. For the same reason, the snapshot images need to be included in your version control repository.

Summary

Will I use snapshot tests for my SwiftUI apps? Yes, definitely. I use unit tests for my model classes but mostly avoid UI tests as they are too clumsy to write and time-consuming to run. Snapshot tests are better for SwiftUI, and very fast.

Name This App

My current work in progress is an iPhone app designed to make it easier to solve crossword anagrams by emulating and improving upon an ability that was there when we used to do crosswords on paper, but is missing for digital crosswords.

But I cannot think of a clever name for the app, so please read the story and contact me with your name suggestions or if you would like to test the pre-release version of this app.

Cryptic Crosswords

Programmers are basically puzzlers, and programming is the world’s best type of puzzle, but I like to start my day with a cryptic crossword. Like programming, cryptic crossword clues have their own syntax and what seems like gibberish on a first glance, can be parsed into logical parts to take you to the answer. But there are aspects of solving crosswords that were easier with pencil and paper, so I decided to write an app to help fill one of those gaps.

My crossword of choice is the Crosaire crossword from The Irish Times. A lot of newspapers have a cryptic crossword and most of them need a subscription, but the Irish Times has a crossword only subscription that I really like. Crosswords also tend to require some local knowledge, but for the Crosaire, if you remember that the Abbey and the Gate are both theatres and that Down is a county, you will have most of what you need. And as an added bonus, the crossword creator later blogs the solutions with explanations so you can learn how the clues were constructed if you are totally mystified.

Anagrams

Anagrams are a very popular clue type but they can be tricky to solve because our brains are too good at discerning patterns. We can recognize words using only the first and last letters if they have the correct number of letters inside. This means that asking our brains to scramble these letters into a completely different word is very difficult. In the olden days, when I used to do crosswords in the newspaper, the best method was to find a space in the margin and write the letters out in a circle which forced my brain to reconsider the options.

Here is an example from a recent Crosaire:

Users rip off revelation (8)

The word “off” is a hint that this is an anagram, “Users rip” has the right number of letters, so the overall clue must be “revelation”. This is not a very long anagram and I think having two words makes it easier, but lets take a look at how I would solve this the old-fashioned way. (And I knew the “I” was the third last letter.)

If you watch this gif and then look at it when it stops repeating, hopefully you will be able to see that the answer is “SURPRISE”. Refresh the page if you want to start the gif looping again.

But I do crosswords on my iPad now and while I could use a notes app and my Apple Pencil to draw the letters out like I did in the GIF above, I don’t always have the Pencil with me and I want to keep looking at the crossword. So I decided that a companion iPhone app was the way that would work best for me.

There are sites and apps that offer anagram solvers, but they are just looking through a dictionary and showing you all the possibilities. To me, this feels like cheating, but I don’t have a problem with using an app to emulate the techniques I used to use with pencil and paper.

App Design

So I planned out the basic features of the app:

enter a word

display the letters in a circle

shuffle these letters if needed

place letters in a possible solution

Arranging the letters in a circle was made relatively easy by using SwiftUI. I placed the letters in a ZStack so they were all piled on the one spot. Then I calculated the X & Y offsets needed to move each letter to the edge of a circle. This involving digging out some long-forgotten trigonometry to convert from polar coordinates to rectangular coordinates. I could calculate the radius of the letter circle based on the screen size and the angle between each letter was 360 degrees divided by the number of letters. So some quick calculations converted these two numbers into X & Y coordinates for each letter, and then I had my circle.

The original word was converted into an array for display, so re-arranging the letters was a matter of calling shuffle() on the array which automatically triggered a SwiftUI redraw.

And here is version 1 of the interface running in the SwiftUI Canvas:

Refresh the page to see the gif play, if it has stopped.

A Different Type of Anagram

Now we come to a variation of the anagram clue that is very popular with the author of the Crosaire crossword. I don’t know if there is an official name, but I call them “subtraction anagrams”.

Here is an example:

Creationist has no taste for what’s sarcastic (6)

The idea here is to remove the letters in “taste” from the letters in “Creationist” and then unscramble the remaining letters to find a word that means “sarcastic”. My first attempt at this used a Trash can button that removed the letter and shortened the space for the solution, but then I decided to have a discard tray at the bottom of the screen to show what had been removed and allow replacing any letters discarded by mistake.

After this, I added a bit of style to make it look nicer and then moved on to the next feature. If I knew some of the cross letters already, I wanted to be able to place them in the solution squares and then lock them in place. This would allow me to shuffle in letters to test and remove all the unlocked ones with a button click. So here is what the app looked like after those changes:

Refresh the page to see the gif play, if it has stopped.

Drag & Drop

My next experiment was with drag & drop to place or discard letters. I waited until iOS 13.4 brought drag & drop to SwiftUI but I was not happy with the result. Firstly, there is a big lag on dragging. You have to hold your finger down on a letter for quite a while before it becomes draggable. This was so counter-intuitive that I thought it wasn’t working, but occasionally it did work and so I eventually deduced that it was a timing issue.

The second problem was solved thanks to a suggestion by Luis Ramos on Twitter. When I dragged a letter, the drag preview image was the shuffle button from the middle of the ZStack instead of the selected letter. This was solved by moving the onDrag modifier to BEFORE the offset modifier (not AFTER like I said in my original response to Luis). But I was still not happy with it, so I decided to discard this idea and stick to tapping.

There was one side-effect: I wasn’t able to get the drag preview to be round - it was a square with opaque corners. As a work-around, I changed the letters to be inside squares and then decided this was a better look anyway, since it was more like what you see in a crossword.

Further UI Enhancements

I installed a custom font so that it looked more like hand-writing. I wrote about installing custom fonts in a separate article, so if you are interested check that out for details on the multiple steps that you need to take to get them to work. I went through a few different fonts until I found one that I thought worked well and clearly for all the upper case letters but I settled on Oregano. And then I made the app work in dark mode too:

The clue for this one is “Consumables minus bacon and shellfish (6)"

Animations

SwiftUI has animation built in, so I was able to add an animation modifier to the various views to make the transitions look smooth. I particularly liked the way the letters re-arranged themselves around the circle when I removed or replaced a letter.

But to add something extra, I thought it would be fun if the letters all started in the middle and moved outwards to their places on the circle. The way I did this was by using a Boolean to store whether the letters had had their first draw. If not, the radius of the circle was zero, so they all piled in the middle. After a delay, this Boolean was toggled so the radius was changed to the full size and the animation modifier already applied, made the letters smoothly expand outwards.

For the letter shuffle, I did the reverse, moving the letters in, shuffling, then moving them out again.

Refresh the page to see the gif play, if it has stopped.

I also added sound effects and a slide-up sheet view with settings and help. I enjoyed using Apple’s SF Symbols to show icons for each paragraph of the help, although I may change the colour of these icons as they look at bit too much like buttons right now.

Next Steps

Well, I am hoping that someone will come up with a good name. I thought of “Anagram Assistant” but that doesn’t fit underneath the home screen icon and it was shortened to “Anagram”. I don’t want people to see it and think it is just one of those dictionary lookup anagram finders, so I would like something more descriptive while still being short, or at least having a short variant.

In honour of P.G.Wodehouse’s favourite crossword clue, I thought of calling it “E blank U” but that isn’t an anagram, so it doesn’t really work. For people not familiar with that reference, Wodehouse’s less quick-witted characters always get stuck on “Large flightless Australian bird, 3 letters. E blank U”.

A clever name would be good - perhaps an anagram itself? If you think of anything, please let me know on Twitter, by using the email link below or through the Contact page. The namer will get full credit in the app. And use one of those methods to contact me if you would like to test the app before it is released.

Once I have a name, I can get to work on the usual secondary tasks which take so much time: App Store set up, screen shots, a support page and so on.

I haven’t tried an iPad version yet. I got stung once by testing an iPad version of an app, deciding it didn’t work well and then running into Apple’s ban on dropping a platform from a published app. This has discouraged me from iPad apps ever since, which I doubt was their intention.

And if you are curious about the solutions to the clues I used in the examples:

SwiftUI Color

As developers, we are used to thinking of color as a numeric way to specify a particular tint. But in SwiftUI, Color - like almost everything else - is actually a View in its own right. This leads us to two very interesting questions: how do we use a view to specify a color and how can we use the fact that Color is View?

Specifying a Color

To start my investigations of Color, I created a new iOS single view app in Xcode. Regular followers will know that I am a passionate advocate of macOS programming, but when experimenting with SwiftUI, I prefer to use an iPhone app as the preview canvas fits very neatly into the main Xcode window.

The default ContentView contains a single Text view. To change the color of the text in this view, I added a modifier:

Text("Hello, World!")
.foregroundColor(.red)

The foregroundColor modifier expects a Color so there was no need to tell it that the parameter is a Color and I was able to use the short way of describing one of the standard colors.

Adding a background color is a bit different because a background can be any view, not just a color. So the modifier needs to specify that this is a Color view, as well as setting the actual color.

I added the padding to make the overall size bigger so that the background color was more obvious.

Command-click on .red or .yellow in the code and select “Jump to Definition”. This lists the available pre-defined colors. As well a set of basic colors and a clear option, there are two extra entries: primary & secondary. And if you scroll back up the page a bit, you will see another one: accentColor.

Choosing one of the preset options is the easiest way to select a color. But try this:

In your code, type let uiColor = UIColor. and have a look at the auto-complete suggestions that appear after you type the period. Scrolling past the various init methods, you will see that UIColor has a lot more options than Color. There are a bunch of colors, a section of system colors and a lot of semantic colors like placeholderText, secondarySystemBackground.

Why does UIColor get these other useful looking options and Color does not?

Well, I don’t have an answer to that except that I hope they will appear over time. But in the meantime, it is easy enough to create a SwiftUI Color from a UIColor.

If you know the RGB values of the color you want to use, it is possible to create a Color directly by various methods like this one for setting the color using the RGB values.

let rgbColor = Color(red: 1.0, green: 0.5, blue: 0.5)

But when you get to this stage, I strongly suggest that you start using color assets instead.

Using Color Assets

Go to Assets.xcassets and click the plus button at the bottom of the list of assets. Select “New Color Set” and you will get a new asset called “Color”. You can double-click the name to edit it to something that makes sense to you.

While naming it after the color may seem logical, I prefer to think about the use cases for this color and set the name to something like “cardBackground” or “alertText”.

By default, your new color set will contains a single color block. Click in the color block itself and then you will be able to edit the color in the Attributes Inspector. If you click the “Content” popup, you will get access to all the system colors, and you can also select any color space and create a custom color using that color space. Click “Color Panel” to access a standard color picker if you need it. And change the input method to whatever suits the color information you have.

Modern apps need to be able to handle light and dark modes, and this is where using a color set really shines. Set the color to what you want to use for light mode and then choose “Any, Dark” from the Appearances popup menu in the Attributes Inspector.

Now your color set has two blocks and you can change the Dark one to whatever color this should be in dark mode. This feature of Color Sets is a very strong argument for using them instead of defining colors using their RGB values.

And now for the really neat part. To use any of these color sets in your code, add a modifier like foregroundColor just the same as usual, but when the placeholder for the color is selected, press Shift-Command-L to bring up the Library palette and choose the Color icon at the right. You will see all your color sets there and you can insert them easily and accurately.

Here is the code for my AlertView using two color sets.

Some people may object to using “magic strings” to specify the color sets but I feel that so long as the Library is used to insert the color names automatically, there is very little chance of error. But you could always make an enum or struct of color name constants and use these instead.

The canvas shows two previews: one for light mode and one for dark mode.

If you have a color picker app (I use Colorpicker), you can detect the RGB values in the two previews. I made the font bold to make this easier. Red is rgb(232, 77, 61) in light mode but rgb(233, 85, 69) in dark mode. And the others have similar modifications to make them look their best in each environment.

Take particular note of the three at the bottom of the list: primary, secondary and accentColor. These are incredibly useful when making a layout that works in both light and dark modes.

When choosing a UIColor or NSColor, it is best to use the system versions, so .systemBlue instead of .blue as this gives the dark/light variants that we just saw. And the other semantic colors like UIColor.secondarySystemBackground also have dark/light variants automatically.

Color as a View

Now let’s consider the effect of Color being a view and not just a description of a tint. Imagine you wanted to draw a colored box on the screen. Using UIKit, you would probably think of using a UIView. With AppKit, maybe an NSBox. Or perhaps you would have jumped straight to a Bezier path.

Create a new SwiftUI view and replace the default Text with a Color, like this:

structBoxView: View {
var body: some View {
Color.blue
}
}

Resume the canvas preview and you will see the color fill the preview iPhone screen, except for the safe areas top and bottom.

To make this into a box, add a frame modifier with the required height and width. And now you have a box, far more easily than you could in either UIKit or AppKit.

To be honest, in SwiftUI, you would probably use a Rectangle instead of a plain Color if you wanted a box of a set size but it is interesting to consider how Color could be made to work.

Custom Fonts in iOS & macOS apps

As a rule, I prefer to use fonts that come pre-installed with the system. That means that your interface is already familiar to users, you get dynamic font sizing and if Apple updates the fonts, you get the updates without doing anything.

But sometimes, you really need to use a different font in your apps, and as the process of getting a custom font to display in your app can be confusing and tedious, I thought I would go through the steps for both iOS and macOS apps.

I probably should have published this on a different day, but it is not a joke…. really.

Getting a Font File

The first thing is to find a suitable font and make sure that the license for that font matches your use. I wanted a font that looked like it was hand-written, so I went to fontspace and searched the hand-writing category there.

Since I wanted to use this in a paid app, I checked the “Commercial-use” button to limit the search. The one I chose was called “Painting With Chocolate” by “Make mooze”

I downloaded the font and un-zipped the file which gave me a single file called “Paintingwithchocolate-K5mo.ttf”. You can use either “.ttf” or “.otf” font files.

Using the Font in an iOS App

Now to use the font, first in an iOS app. Boot up Xcode and create a new SwiftUI project for iOS.

Once the project is open, drag the font file into the Project Navigator. At this stage there are 2 crucial settings:

Check “Copy files if needed”.

Check your app in the “Add to targets” section.

In one of my tests, the file stayed in the Downloads folder even after checking “Copy files”, so I deleted the reference, manually moved the font file to my project folder and added it again.

Now the font file is in the project but there is still more work to do.

Select the font file in the Project Navigator. Press Return as if you are going to edit the name. Select the complete file name, including the file extension and copy it.

Now go to the Info.plist file. Right-click in the blank space below the existing entries and select “Add Row” from the popup menu. In the box that appears, start typing “Font” using an upper-case “F”. When you see “Fonts provided by application”, select that.

This entry is an array. Click the disclosure triangle to the left and you should see “Item 0” appear. Paste the name of your font file, including the file extension, into the value for “Item 0”.

Your app now has a font file and knows to make it available. But you aren’t finished yet.

To use a custom font, you need to know its exact name. In SwiftUI, the code will be something like this:

Text("Hello, World!")
.font(.custom("Font-Name-Goes-Here", size: 14))

But the exact name is not always obvious and is rarely the file name. So the best thing to do is to ask the app what fonts it now has available. This will also act as confirmation that the font file is being included correctly in your project.

You can run the app in the Simulator or use “Debug Preview” to make this show up in the console, but once you have the list, scroll through in until you find the font you just added. The headers are the names of font families and the indented entries are the font names themselves.

This time I found that the name of the font was quite obvious: “PaintingWithChocolate” but this is not always the case. And if the font has any variants, you will need to use the complete name e.g. “Optima-ExtraBlack”

With the name of the font, you are finally able to use it in the app, like this:

Using the Font in a Mac App

Install the font file in your project as before, making sure to copy the file into the project and to add it to the app target.

For a Mac app, you do not need to specify the font file name in your Info.plist file. Instead, you have to tell the Info.plist where to look for custom fonts in your project directory.

Open your Info.plist, right-click in the blank space below the existing entries and select “Add Row” from the popup menu. Start typing “Application” using an upper-case “A”. When you see “Application fonts resource path”, select that and enter a period as the value. A period or full-stop tells Xcode that you mean the current directory but even if you have your fonts in a sub-directory, this seems to work.

You do not need to set “Fonts provided by application” for a Mac app, although if I had a problem, I would set it as I feel that this is something that Apple may add at some stage.

While I was using the same font for both apps and so already had the exact name, you may still need to check the list of installed fonts in a Mac app. The function for doing that is quite different:

Storyboard apps

The examples above were both SwiftUI projects, but these techniques work much the same in a storyboard project.

Follow the same steps to install the font and configure the Info.plist file and use the same functions to list the installed files.

To use the fonts, if you are using a storyboard in an iOS project, select “Custom” in the font picker and then you will be able to see your custom font listed if it is installed correctly. I could not work out how to get the custom font appearing in this menu for a macOS app.

SwiftUI for Mac Extras

Last year, I wrote a 3 part series of articles on using SwiftUI to build a Mac app. I would like to thank everyone who contacted me about this series. It was received very well and revealed that there is still a large amount of interest in programming for the Mac.

Some of the responses I got were pointing out different or better ways to do things, so I am going to list them here, adding to this post as I get new information. The relevant sections in the original posts will have links to the fixes suggested here, but I decided it was easier to list the changes in a separate post, rather than asking people to re-read the whole series looking for modifications.

Dismissing sheets

I just read your series on writing Mac apps with SwiftUI. Great stuff!
Just wanted to add that in part 2 when dismissing sheets there are two ways to do that, one of them is the one that you figured out and the other is to have the view dismiss itself by grabbing its PresentationMode from the environment. This way you don’t need to pass presentation bindings to your sheet views.

I guess the presentation mode method is slightly easier to understand and it leaves the caller of the sheet view less cluttered which is a good thing. But the two methods are functionally identical, so use whichever you prefer. The sample project now contains both methods, with one commented out, so you can swap the comments to test.

Subscribing on the Main Thread

In part 2 of this series, I created a menu item caused the downloaded image to be flipped. Selecting the menu item posted a notification:

Since the notification was triggering a change to the UI, I made sure that this happened on the main thread.

But it was pointed out to me that it would be easier to make sure that the publisher was set up to use the main thread all the time, instead of having to specify the main queue when processing the notification.

I noticed that the selectedColor in the EmbeddedColorWell is not being mutated and is not being used in a two-way manner. The selectedColor is initialized to NSColor.blue and used to set the color in the NSColorWell view. When the NSColorWell color is changed, it does change the color of the EmbeddedColorWell view. However, the actual @State var selectedColor value is never mutated in this process beyond the initialized value of NSColor.blue.

This is in the Form tab of the UI Samples window. As suggested to me, I added a background modifier to set the background of a portion of the view to the selected color. And although the NSColorWell showed newly selected colors, the background remained stubbornly blue.

The solution was to add a Coordinator to the NSViewRepresentable and have it subscribe to any changes in the color and update the embedded view’s selected color as needed. I would not have come up with this by myself, so many thanks to the person who sent it to me.

In the previous section, I changed the publisher to use the main RunLoop so as to avoid having the use DispatchQueue.main.async. In this instance, that did not work so well. It only updated the selected color after the mouse had been released. But using DispatchQueue.main.async made the update live.

As I explained at the start of these articles, I was documenting my explorations in using SwiftUI for a Mac app and while I hoped there would be some useful examples, this was not intended to be a definitive guide. So I am very grateful to everyone who has contributed to these updates.

If you have anything more that you would like to be included, please contact me using one of the contact buttons below or through the Contact page on this site.

SwiftUI for Mac - Part 3

In part 1 of this series, I created a Mac app using SwiftUI. The app uses a Master-Detail design to list entries in an outline on the left and show details about the selected entry in the detail view on the right. In part 2 I explored using menus, adding all the expected user interface elements and opening secondary windows.

In this third and final part, I want to look at the various ways to present dialogs to the user.

There are four different types of dialog that I want to explore:

Alert

Action

Sheet

File dialogs (open & save)

So the first thing to do is add a footer to the DetailView to trigger each of these. I am going to separate this out into a new subview for neatness.

Alert

To make an Alert, I need an @State Bool which sets whether the alert is visible or not. All the button has to do is toggle that Bool. Stripping out the extra code and views, this is what I have.

To configure the alert itself, I added an alert modifier to the outmost view in this view. The dialogResult string is a diagnostic that I can use to confirm that the results of the various dialogs get passed back to the parent view.

There were a few things that tripped me up in this relatively short chunk of code. Firstly, both title and message must be Text views, not strings. If you get an error message that says “Cannot convert value of type ‘String’ to expected argument type ‘Text’", then you have forgotten to use a Text view.

Then there is the button which auto-suggest tells me is of type Alert.Button. I couldn’t find any documentation for this, but delving into the definition for Alert, I see that there are three pre-defined button types: default, cancel or destructive. Cancel actually has two variants and will use a label appropriate to the user’s locale if no label is supplied.

Again, these buttons need a Text view as the label (if supplied) and can take an action closure, which I used to update my dialogResult string.

This version showed a single dismissButton but I saw that there was a variation of Alert with primary and secondary buttons. It was not obvious that these would also dismiss the alert dialog, but I tried anyway.

This worked very nicely and the Esc and Return keys triggered the two buttons as you would expect with both of them closing the dialog.

I tried using the destructive button type, but there was no difference to either the appearance or behavior of the button.

So Alert is a great choice for a text-based dialog, either for informational use or to allow two choices of action.

Action

Very short section here - ‘ActionSheet’ is unavailable in macOS! I probably should have researched that before I started this section. So use Alerts, I guess or a custom sheet.

Sheets

While Alerts have a very fixed structure, sheets allow us to put any SwiftUI view into a sheet dialog.

So I added another Bool for the Sheet button to toggle, and added this sheet modifier. SheetView right now is simply a TextView.

.sheet(isPresented: $sheetIsShowing) {
SheetView()
}

This didn’t work so well. It showed the sheet, but the sheet was tiny - only the size of the Text view it contained. And I had no way of dismissing it…

The size problem was solved by setting a frame on the Text view in SheetView.

The trick to dismissing the sheet is to pass it a Binding to the Bool that triggered it to open in the first place. If a button in the sheet sets this Bool back to false, the parent view will hide the sheet. That sounds confusing, but it works.

The parent view has an @State Boolean variable called sheetIsShowing. This is bound to the alert’s isPresented so it dictates whenever the sheet is visible. When the Sheet button is clicked, this variable is set to true and the sheet opens. But at the same time, a Binding to this variable is passed to the sheet. I deliberately gave this a different name, so as to make it clear which View was changing what variable.

When the sheet wants to close, it does not close itself. Instead it sets this variable to false. Because it is a Binding, this sets the original sheetIsShowing variable on the parent view to false and the parent view then closes the sheet.

UPDATE: Look at Dismissing sheets in my post of extras & changes to this series for an alternative way to dismiss a sheet.

Sheets & Data

With this in place, I had the sheet opening and closing perfectly, but I was not yet passing data back & forth between the sheet and its parent view. I decide to put a TextField in the SheetView and bind its contents to the dialogResult property in the DetailView so that any edits appeared immediately in the DetailView. And while I am there, I might as well add some more decorations to the SheetView since it is a full View and not a restricted Alert.

I only had two issues with this now. I was not able to get the focus into the TextField automatically when the sheet opened and I was not able to assign keyboard shortcuts to the Cancel and OK buttons so that they could be operated without a mouse. And as I mentioned in the previous part, I was not able to make the OK button take on the default styling.

One useful technique that I developed: the SheetView is in the DialogsView.swift file instead of in its own SwiftUI file. It would probably be a good idea to separate it out but I didn’t which meant that it had no Canvas preview to look at while I was laying it out.

So I edited the PreviewProvider like this, so that I could change the comments to switch it between showing the DialogsView and showing the SheetView.

Files

AppKit provides NSOpenPanel for selecting a file and NSSavePanel for saving. I will try to implement NSSavePanel to allow saving the current cat image.

Since this is an AppKit control rather than a SwiftUI control, I assumed that I would need to use NSViewRepresentable like I did for the NSColorWell in part 2. But while NSColorWell is a descendent of NSView, NSSavePanel is not. So I need a new idea.

Rather naively, I thought maybe I could just create an NSSavePanel in a function inside DialogsView and see what happened.

Crash & burn… so what if I made the NSSavePanel an @State property of the View? No, that crashed even faster. Maybe SwiftUI Views don’t like this sort of thing, but how about if I get the Application Delegate to handle it? What if I moved the saveImage method to the App Delegate and changed the calling function to access it there?

Still crashed. At this stage I am beginning to wonder if I know how to use an NSSavePanel. Time to create a simple test app without SwiftUI and see what happens. Well it appears that I no longer know how to use an NSSavePanel. Code from an older project that works fine, will not work in my new sample project!

Guess what - it was another macOS Catalina security issue which I would have realised faster I had opened the Console. Back to the Signing & Capabilities section of the target settings and this time I set File Access for User Selected File to Read/Write.

Now the NSSavePanel opens when called from DialogsView and prints the selected file URL if one is chosen.

But this is all happening in DialogsView, which is a subview of DetailView. And DetailView is the view that holds the image, not DialogsView. So how can I save the image? Do I pass the URL to DetailView or pass the image to DialogsView? Or do something clever with Notifications and Subscriptions?

I really don’t know what is best, but I have decided to post a Notification with the URL as its object. DetailView can receive this Notification and save the image whenever it is received.

And there we have it. Three types of dialogs demonstrated in a SwiftUI for Mac app:

Alerts: good for simply text-only dialogs

Sheets: good for more complex dialogs

Panels: AppKit dialogs that can be called from a SwiftUI View.

I think this time I really am finished. This article has already expanded out into a 3-part monster, so I think it is way past time that I stopped typing. I hope you have enjoyed this series. Please use any of the buttons below to contact me or use the Contact page on this site. I would love to hear from anyone who found this series useful or who had any suggestions or corrections to make.

The final project is available on GitHub if you would like to download it and take a look.

SwiftUI for Mac - Part 2

In part 1 of this series, I created a Mac app using SwiftUI. The app uses a Master-Detail design to list entries in an outline on the left and show details about the selected entry in the detail view on the right.

Now it is time to explore some more of the features of a Mac app with SwiftUI.

Menus

I had already discovered that the menu bar is configured in the Main.storyboard file. As an experiment, I will add new menu items that allows the user to select between dark mode, light mode or the system mode.

Looking at the possibilities along the top that I could send the menu command to, the App Delegate looks like the best option, especially since these menus will change the entire app.

I opened AppDelegate.swift in the Assistant Editor and Control-dragged from each of the new menu items to create the 3 IBActions and added the code to set the mode.

And since I realized that I would want to check or un-check these based on the current settings, I added IBOutlets for each of these menu items too. As a side note, I love how Xcode is now clever enough to decide whether to add an IBOutlet or an IBAction depending on where in the file you Control-drag to.

Using a Property Wrapper

Changing mode worked perfectly in the Xcode Preview and in the built app, but the app was not storing this or displaying the current selection with a check mark in the menu.

It would be neater to use an enum here instead of strings, but that would have required fiddling with rawValues to save the data, so for this first test, I stuck to strings.

The code to toggle the checkmarks in the menu items is standard stuff and nothing particularly SwiftUI related, so I won’t detail it here, but it is in the GitHub project if you are interested.

Passing menu data to a View

This worked fine and the app worked equally as well in dark or light modes, but I wanted to test how to communicate data back from the menus to the SwiftUI views.

As a totally pointless but possibly amusing feature, I decided to add a menu item to flip the cat image and then work out how I could send that to the ContentView.

I added the new menu item to the Format menu and as a first attempt, I tried to Control-drag from there into the ContentView. It didn’t take, so I guess I need to send the message to the AppDelegate as before and then pass it on to the ContentView. I feel like this might be a good place to use a Publisher although so far I have only used the built-in ObservableObject type publishers.

In this case, it would make more sense to have the DetailView respond to the menu, since it contains the image. But trying to add an @IBAction to a SwiftUI View struct gives this error: Only instance methods can be declared @IBAction so I am using the App Delegate instead. I feel like this is a problem I need to solve, or the AppDelegate is going to end up filled with @IBActions, but for now, let’s keep going.

In AppDelegate.swift, I added the IBAction for the Flip Image menu item and had it issue a Notification, after setting up an extension on Notification.Name to de-stringify the name of the notification.

In DetailView.swift, I set up a Boolean @State property to store whether the image was flipped or not and added an onReceive handler to toggle it. Since this is updating the UI, I made sure that it happened on the main thread, but I am not sure whether this is necessary, or whether onReceive uses the main thread automatically.

UPDATE: Check out Subscribing on the Main Thread in my post of extras & changes to this series for an alternative way to make sure the updates happen on the correct thread.

Once I had that Boolean property, I added two more modifiers to the image. Don’t hate me for the force un-wrapping. I tried using if-let but it wouldn’t compile so I check for catImage != nil before using this force-unwrap.

Now the image can be flipped from the menu item or even by using the keyboard shortcut. And with a smooth animation (smoother in the app than in this gif).

Opening another window

For my next challenge, I want to open a second window that I can use to show samples of various UI elements. As I want to open it from a menu command, my first thought was to add a Window Controller to the Main storyboard and open it that way. I replaced the default View Controller with a Hosting Controller so that I could insert my SwiftUI View into it.

I had great trouble finding any documentation or examples of how to implement this, but after a lot of trial and error, here is what I got to work:

Drag a Hosting View Controller into the storyboard and connect it to the menu item with a segue.

Set the Presentation property for the window controller to Single so that multiple copies of the window are not created.

Create a new Swift file and subclass NSHostingController. Don’t bother using a Cocoa class file - the template doesn’t work. Use the code below, replacing SamplesView with the name of the SwiftUI view you want to display.

Back in the storyboard, set the class of the HostingController to this sub-class: SamplesHostingController in my case.

Set a minimum size for the new Window Controller, otherwise it shrinks to a very small stripe on the screen.

Add the .frame(maxWidth: .infinity, maxHeight: .infinity) modifier to the root view in the view you are displaying - my SamplesView.

With all these in place, I was able to open and close a Samples window that was displaying my SwiftUI content.

User Interface Elements

Not all the expected user interface elements are available in SwiftUI and some of the ones that are implemented are using different names. Again this is a point at which iOS development has got all the attention, so there are conversion tables out there listing UIKit elements and their SwiftUI equivalents, but I was not able to find a similar listing for AppKit. If you find one, please let me know.

Anyway, I experimented and got most of what I wanted as you can see below. The sample app on GitHub shows the SwiftUI code for these samples, but the main advice I would give is firstly to use the Object Browser to look for what is available and then to check out the styles that can be applied to the element you have chosen.

Mostly, I managed to achieve what I wanted but there were a few exceptions.

Buttons were a bit odd as there are multiple button styles listed, but I found that they either all looked the same or they disappeared completely. I was not able to style a button with an image and text which is now easy to do in iOS. And I was not able to set a button as the default button and I could not work out how to set a keyboard equivalent for a button. (Setting the keyboard equivalent to Return or Enter might set it to the default style automatically.)

Of the other UI elements that I wanted to use, a color picker was the main one missing. So I decided to embed an NSColorWell from AppKit into my SwiftUI view.

The process for embedding a UIKit view is quite well documented elsewhere and the AppKit equivalent was not significantly different. Replace every “UI” with “NS” and you are nearly there.

First I made a struct that conformed to NSViewRepresentable and had the required two functions: makeNSView(context:) and updateNSView(_:context:). I supplied an @Binding variable to hold the selected color as an NSColor since that is what the NSColorWell uses.

Back in my SwiftUI view, I was then able to use EmbeddedColorWell just like any other SwiftUI view, passing it a binding to an @State variable to set and get the selected color.

EmbeddedColorWell(selectedColor: $selectedColor)

UPDATE: Be sure to read Passing data back from AppKit in my post of extras & changes to this series. This is an important fix that is needed to make this embedded control pass data back properly.

The other stumbling block that I encountered was that I had no way to close the window programmatically, in response to a button click or some other interaction. Maybe this was not the best way to open a fully SwifUI window, but it was still an interesting experiment.

One thing I learned while working on this project was that SwiftUI can be a bit too clever about working out what needs to be redrawn in the previews. If you edit something in an separate file to the View, you may need to force a re-build to get the updates to show.

Communicating Between Windows

The last feature that I need to explore is transferring data between two windows. I tested using a .sheet modifier to open a dialog and that worked exactly as it would in an iOS app - I was able to pass an @Binding variable to the sheet window and any changes made to that in the sheet window flowed back to the calling view.

But I want to set up a Preferences window which will be opened from the menu bar and not directly from the ContentView or any of its sub-views.

I started out by using the same technique as before with a Hosting View Controller. And here is where I came mightily unstuck as I could not make a data connection. I had hoped an EnvironmentObject would work, but I could not get an EnvironmentObject through to the HostingController as it was not in the same view hierarchy.

So instead of trying to use the storyboard, I decide to see if I could use something similar to the initial window creation and call that new window from my ContentView so that it was part of the view and therefore the data hierarchy.

As usual, there was a lot of trial and error involved here, but I came up with a workable solution.

For convenience and reusability, I made an extension on NSWindow that created a window with the basic properties configured, much like they are in AppDelegate. I temporarily added a Button to ContentView like this:

Button("Prefs") {
let _ = PrefsView()
}

This opened the window perfectly, but it had a problem: repeatedly clicking the button kept opening a new window instead of bringing the existing one to the front.

After a lot more trial and error, this is what I ended up with for my PrefsView struct:

And this gave me what I was after - a view that opened from a menu item but that knew itself whether it still had a window so could decide whether to open a new one or bring the existing one to the front. This looks a bit convoluted, but it doesn’t appear to cause any memory leaks and the responsibility for the window rests on the view that uses it, which feels right to me.

After I had this working, getting the data passing around was quite simple. I created a Prefs class to store the preference data. I wanted this data stored in UserDefaults, but since I also wanted to use an ObservableObject with the @Published property wrapper, I was not able to use the @UserDefaults property wrapper that I had used for the app mode.

So instead I used @Published with a didSet that saved the changed data to UserDefaults. Thanks to @azamsharp for this technique.

This preference will dictate whether a copyright notice is shown on every cat image, so it needs to be available to DetailView and to PrefsView. Since I did not want to pass it through every view on the way to DetailView, I decided to use an EnvironmentObject. But I was not able to work out how to set the environmentObject for the PrefsView as I created it, so I ended up sending an @ObservedObject to PrefsView but using an @EnvironmentObject for DetailView. (Actually for CatImageView as I had extracted the image from DetailView as a subview.)

SwiftUI for Mac - Part 1

So far, nearly all the articles I have seen about SwiftUI show it being used for iOS, more particularly for iPhone.
But SwiftUI works on all Apple’s platforms, and as I am primarily a Mac developer, I decided to try out a Mac app and see what happened.

Setup

I opened up Xcode and created a new project selecting the macOS App template. The project opened at the usual ContentView.swift but there were a few differences in the project structure as well as one in the ContentView struct.

The first thing to notice is that the default “Hello, World!” Text view has a frame set:

.frame(maxWidth: .infinity, maxHeight: .infinity)

If I removed this frame modifier, the preview display in the Canvas changed so that the view was only the size of the text instead of being a standard window size. I guess an iOS device always knows what size it is, but a Mac window can be any size, so you have to be more explicit to stop SwiftUI shrinking the container view to the minimum size possible.

The next thing is to look at the files that are included in the project. There is no SceneDelegate.swift as you would see in an iOS project. And to my surprise, there was still a Main.storyboard file! And going to the General settings for the app target, I could see that this storyboard was selected as the Main Interface.

Opening it up reveals that this is where the application menu is configured. I had wondered where the menus were configured in Mac SwiftUI apps.

The AppDelegate was the next thing I looked at and here I found some of the code that I would have expected to find in a SceneDelegate. The applicationDidFinishLaunching(_:) method creates an instance of ContentView, creates an NSWindow and uses an NSHostingView to display the ContentView inside the window. At this stage, running the app gives me what I would expect: a fully-fledged Mac app with a window and a menu, both with all the functions you would expect in any standard Mac app.

The Canvas

I was not expecting the Canvas to be much use when it came to previewing a Mac app. It works so well with an iPhone app because the iPhone is tall and thin and fits neatly into one side of the code window. But a Mac view is likely to be much bigger, so it would have to be scaled down a lot to avoid talking up too much precious space in my Xcode window.

But it works as expected, and even scaled down, you get a good idea of the layout while still getting the live reloading that is part of what makes developing in SwiftUI so much fun.

But here is where I got my first real surprise, with a feature that I had not seen yet in any SwiftUI tutorial or article. Click the Live Preview button and see what happens…

Of course I clicked “Bring Forward” and there was my app running in a window called “Xcode Preview”. There was an app in my Dock and when I chose “Show in Finder”, I found that the app is buried deep in DerivedData. Positioning my windows so I could type in Xcode while watching this preview window, I saw that it instantly updated my view as I typed, just like an iPhone in the Canvas.

If I changed the structure of the view, the app closed and re-opened immediately with the new content. This is amazing and shows that the Xcode & SwiftUI teams really thought about how to use these new features in Mac apps as well as iOS.

In Xcode 11.3, I found that I was having trouble with the previews. They would not display and above the Canvas, I got the super helpful message “Cannot preview in this file — SwiftUI-Mac.app may have crashed.". It turned out that this was a signing issue. If you go to the app target and look in the Signing and Capabilities section, check that Signing Certificate is not set to “Sign to Run Locally”. If it is, switch to “Development” and the previews will start working again.

Laying out the View

Now that I have the project and I know how to preview it, it’s time to work out what to display in the app. The next real app I want to work on will use a master-detail layout, so that is what I decided to try here.

Before worrying about the data, I decided to try populating the master view with a static list and using that to navigate to a detail view that was simply a Text view.

This worked, except that the left column was only about 20 pixels wide. But I was able to use the mouse to drag it wider and there were my List entries. Clicking on one did indeed show the detail I wanted, but it shrunk the window to one line high!

The first thing I did was to apply a listStyle modifier to make it show the semi-transparent Mac sidebar. This fixed the width of the sidebar. But the whole window still shrunk when I selected an item.

.listStyle(SidebarListStyle())

I tried applying the frame modifier to the NavigationView and that made the window stay the same size, but the content still shrunk into a tiny section in the middle. It looks like I need to apply that frame modifier to the detail view as well.

.frame(maxWidth: .infinity, maxHeight: .infinity)

And as you can see from this gif, I then had a full functional master-detail view with a collapsible and expandable semi-transparent sidebar.

Adding Data

After some scouting around for a free API that I could hook into, I came across HTTP Cats which is a site that serves up a cat image to match almost every HTTP status code.

This sounded ideal: I can list the codes in the master view on the left and display the image in the detail view on the right.

First I created a JSON file to list all the HTTP status codes so that I could put them into a List view. This was a very simple array with each entry having a code and a title:

I created an HttpStatus struct with these 2 properties and I borrowed Paul Hudson’s excellent Helper Bundle extension to decode the JSON file. For a first attempt, I used the numeric codes to build the list and showed the title of the selected one in the detail view. But one of the best things about SwiftUI is that it makes it so easy to configure table rows, so it is time to create a new View to do this.

After some experimentation, I had a TableRowView that I liked the look of, but the default sidebar width was too narrow and truncated the status code titles, so I added a frame modifier to the List to set a minimum and maximum width for the sidebar.

Outline List

At this point I decided that it would be more useful to have a outline list with the status codes grouped by their category.

So I re-did the JSON file to show this, added an HttpSection struct and a SectionHeaderView and modified the data loading method and @State variable.

This worked really well and I was thrilled to find that the sections automatically had Show/Hide toggles!

Detail View

Up until now, I had been using a standard Text view as the destination for my navigation. This is a really useful technique as you can build the interface gradually but have it work from the beginning. But now it was time to create a new view for the details.

I set up the view and added a method that would download the correct cat image when the view appeared but there was no image. After some digging, I realised that sand-boxed Mac apps do not allow network access by default. I went to the Signing & Capabilities section of the target settings and turned on “Outgoing Connections (Client)". And then I had my cat pictures.

It really should have a loading image to display while the cat image is being downloaded, but to my disappointment, I found that the SF Symbols are not available to a Mac app! But I added a Text view to say “Loading…".

Now that I have a functioning Mac app with a Master-Detail view, the next thing is to explore some more of the challenges that will need to be solved before I can write a Mac app completely using SwiftUI.

SwiftUI Data Flow

SwiftUI gives us a completely new way to lay out out user interfaces, in a declarative and responsive way. Your data dictates what is displayed. But this leads to a new problem - how should the data models be constructed and how can they be passed around between the various views that make up your app?

At WWDC 2019, some Apple engineers gave a great presentation on Data Flow Through SwiftUI and I strongly recommend watching the video. But you need to watch it twice. First watch it so that you can get started, and then, when you feel that this is all way too complicated, watch it again and it will start to click into place. The only real difference between then and now is that BindableObject has become ObservableObject.

I guess I could stop there, but I will be illustrating my ideas with code examples, which I hope will make things clearer. Some of the examples are rather contrived in order to make a point, but the sample code is also sprinkled with other SwiftUI examples which I hope will prove useful.

Download the sample project from GitHub and open it in Xcode. Go to ContentView.swift and make sure the Canvas is open. Click Resume to make the view appear. Then click the Live Preview button and wait for the view to become active. I recommend clicking the Pin button at the bottom left of the Canvas so that you can investigate the code samples, while still working in the main navigation.

Data Flow Options

There are 5 ways to specify data in SwiftUI:

Property

@State

@Binding

ObservableObject & @ObservedObject

@EnvironmentObject

Property

In this example, the greeting property is used in the view. greeting is static, so the view does not need to monitor it for changes. This may seem like a simplistic and obvious example, but separating it out allows for localization or re-usability.

The property could also have been supplied by a parent view and this is a really useful feature of properties. A parent view can have some dynamic data that it can use to set properties in a subview where the subview only needs to display the data statically. This data will change as the parent view changes but the subview will not be able to change the data in the parent view.

And it is important to remember that not everything needs to be set up with one of these new property wrappers.

@State

This is where things start to get very interesting in the SwiftUI world. SwiftUI views are contained in structs, so are non-mutable. Also, the views are re-created every time the data changes, so any properties are re-created then too. By marking a property with the @State property wrapper, you are telling SwiftUI that you want it to keep this data in a separate portion of memory, allow it to be mutated, and preserve the current value during the view refresh.

In this example, toggleValue is declared as a Bool with a property wrapper of @State. Inside the Toggle, the isOn value is bound to toggleValue by the leading $. This allows the variable to set the toggle and the toggle to set the variable - 2-way binding.

@State variables are always value types and are usually local to their view, so Apple recommends marking them as private.

And unlike properties, @State variables allow you to have data that is dynamic but it can still be passed to subviews as properties for display.

@Binding

One problem with building SwiftUI views is that it is very easy to end up with a gigantic Pyramid of Doom as you embed views within views within views. The solution is to extract subviews, but then you need a way to pass the data to the subview.

This is where @Binding comes in as it allows you to tell a view that the data for a property is actually coming from a parent but that the subview is allowed to change that property and that change will flow back to the parent’s data.

In this example, I have declared a stepperValue property and marked it with @State.

The interface has been extracted into a subview called NumberChooser and a Binding to the stepperValue property has been passed to NumberChooser using the $ prefix, which will ensure that changes to the value can come back. Inside NumberChooser this property is wrapped in the @Binding property wrapper to indicate that it is coming from another source and that changes will be returned.

NumberChooser itself has a subview called NumberBlock but it is a display view only and never mutates the value itself, so stepperValue is passed to this subview as a property only, without the $ prefix. It will still be updated every time the data changes as it is contained by the view with the @State property.

@State & @Binding - Part 2

So far, the examples have used primitive data types for the @State properties, but given that @State properties are value types, any struct can be used. In the next example, I use a struct to hold the properties of a pizza order and use a SwiftUI Form to allow selections.

The form consists of 3 subviews - one each for selecting the pizza, size and crust. The Pizza struct holds all three properties, but each subview only needs a Binding to the single property that it controls. The Text view after the Form is to prove that all the selections come back to the parent.

ObservableObject & @ObservedObject - Part 1

These are used if your data model is a class and you want to use reference-based data instead of the struct’s value-based system.

To set up a data model to be Observable, it must conform to the ObservableObject protocol and any property that needs to be observed should have the @Published property wrapper. This makes sure that any time this property changes, all the Views that are observing the instance of this data model will be notified to perform the UI updates.

For this example, I have a ColorSet class with six color components that are used to assemble two RGB colors.

The background of the view and the foreground of a system image are set using these colors. A button presents a sheet with sliders to allow editing these colors. The colorSet is passed to the sheet like this:

.sheet(isPresented: $showChooser) {
// notice that this does not use $ as the ColorChooser// will get a reference to the ColorSet object
ColorChooser(colorSet: self.colorSet)
}

A sheet is not the ideal way of presenting a view that uses sliders for editing, but I wanted to demonstrate that changing the sliders instantly changes the value of the @ObservedObject for the parent view as well as for the subview. Editing the background color components shows the new background color in the back at the top of the sheet.

The ColorChooser itself uses 2 subviews and they get a reference to the ColorSet in the same manner.

ObservableObject & @ObservedObject - Part 2

This section was that one that caused me the most trouble when writing the example app. I wanted to display a list of data and have each entry link to an editable detail view with the edits flowing back to the parent list.

The initial display of data in a List was straight-forward and I was then able to have the list rows navigate to a detailed view for each entry. The problem was getting the edited data back to the parent List.

The basic data model was an ObservableObject that publishes an array of PersonViewModel objects.

This almost worked. The correct data was passed to the detail view, and the data edits changed the data, but the parent list was never re-drawn. If I changed a record’s first name then went back to the list, the change was not displayed. But if I then returned to the detail view for the same record, my edits were there, so I could tell that the data was changing correctly. The problem was how to change it in such a way that the parent view was notified of the change.

Trying to bind person with PersonDetailView(person: $person) gave the error Use of unresolved identifier '$person', so the ForEach enumeration did not provide a direct connection to the personList object.

The solution I came up with was to switch to enumerating by index in the ForEach and passing a direct member of the parent list’s data to the detail view. And switching the PersonDetailView to use @Binding var person: PersonViewModel.

This works but as well as being hard to read, it has one major flaw. The rows in the table are identified by their row number, rather than by anything in the data like the person.id. This can really mess with how SwiftUI handles the List and how it knows which rows have changed and need to be re-rendered. It is important to identify rows by something unique to the data in each row so that SwiftUI knows that you have deleted the row with the ID “abcd-1234” and not row #7. Because if you delete row ID “abcd-1234” there is no longer a row ID “abcd-1234” but if you delete row #7, there is now a different row #7 and anything could happen.

Update 1:@StewartLynch contacted me to suggest a much neater way to pass the person data to the PersonDetailView by using a function to get a Binding<PersonViewModel> for each person being displayed. This worked perfectly and made for a much cleaner looking bit of code. Thanks Stewart.

Update 2:@vadimshpakovski says that creating a binding for every person object is inefficient and that the function to create this binding will slow things down. He suggests using onReceive to react to changes to person and trigger an update of personList. In this case, PersonDetailView uses @ObservedObject var person: PersonViewModel. This also works perfectly.

Update 3: More suggestions have come in from the community (thanks to everyone who contributed) and it has been pointed out to me that while Vadim’s solution does solve a lot of the issues, it means that the entire ForEach has to be recalculated to check for changes every time a single Person is edited. And it also inserts model management code into the view code, which is not great.

So my next attempt goes back to using @Binding var person: PersonViewModel in PersonDetailView but instead of PersonListModel having an array of PersonViewModels, it has an array of UUIDs and a dictionary of UUID: PersonListModel. The benefit of this is that the UUIDs can be used in the ForEach as they are unique to each row, and the dictionary can be used to provide a Binding to the person for each UUID.

This removes the problem of my original solution by identifying each row uniquely, it goes back to Stewart’s solution but eliminates the potential slow function to create a binding for the matching person, and eliminates the issue of complete redraws and model management inside views from Vadim’s suggestion.

But it was not entirely straight-forward as getting a value from a dictionary by key returns an optional. At first I thought I could use the new default syntax for dictionaries to get a non-optional value for binding but for some reason that couldn’t be used to create a Binding.

The answer was to write an extension on Dictionary with a subscript function that returns a non-optional value or gives a fatal error. Since I am in control of the data and set up every UUID with a matching PersonViewModel, this is not dangerous.

The incoming data is mapped to a sorted array of PersonViewModels before extracting the UUIDs and creating the dictionary. This means that the UUIDs array is in the correct sort order for use in the ForEach.

This ended up a bit more complicated than my original idea, but I think it is now good SwiftUI, avoiding several problems from the earlier solutions.

Thanks to JSON Generator for the sample data. And if anyone has any other solutions to this problem, I would love to hear it. You can contact me using any of the buttons at the end of this article.

@EnvironmentObject

Think of the EnvironmentObject a piece of state that can be used by any view or any descendent of the view once it has been introduced. People who have used React or any of the similar web development technologies will be familiar with the concept of global state and this is similar to that, although not truely global.

You set up a class as an EnvironmentObject model exactly as you would set up an ObservableObject with the same protocol conformance and using the @Published property wrapper to mark properties whose changes will trigger UI updates. Here is a very simple example with just one property.

In this example, the yellow view is the parent view - the different views have different brightly colored backgrounds to make them easy to distinguish. The yellow view has access to the UserSettings like this:

The ChildView contained in this parent - the green view - has no need to access this data and so gets no @EnvironmentObject property. But ChildView contains another subview - the blue one. And this GrandChildView does need access to the UserSettings so it has the exact same @EnvironmentObject var userSettings: UserSettings property as the parent view.

If this was using @ObservedObject the data would have to be passed through every view in an un-broken chain, even though ChildView did not need this data. By using @EnvironmentObject the chain can be broken, but any view that needs to, can access and mutate this data. In the example, both the yellow and the blue views display and edit the same data with updates happening in both when either button is pressed.

One key thing to remember about previewing @EnvironmentObject in the Canvas is that every view that uses it, or that contains a view that uses it, needs to be supplied with the ObservableObject in the preview using .environmentObject().

In the app itself, only the first view to access the @EnvironmentObject needs it set. In this example, it is done in the NavigationLink that goes to the NestingViews example. The .environmentObject can be provided to the root view in the SceneDelegate if the root view needs it.

Summary

For data needed by a lot of views in your app, use @EnvironmentObject.

Use @Binding or @ObservedObject to pass data to a view that can mutate it.

And one final tip: while creating a view from scratch, use @State with sample, hard-coded data. Once you have the interface you want, then change it to use real data.

I am sure people will develop their own theories and their own ways of using SwiftUI, but those are the guidelines that I intend to follow for now. If you have different views and would like to discuss them, please contact me.

SwiftUI First Thoughts

At WWDC 2019, Apple surprised us all by announcing a completely new declarative UI framework called SwiftUI. Quoting snippets from the Apple announcements, “SwiftUI is an innovative, exceptionally simple way to build user interfaces across all Apple platforms with the power of Swift” and “SwiftUI uses a declarative syntax so you can simply state what your user interface should do.” But what does this mean and should we all adopt it now?

Swift

Before discussing whether to adopt SwiftUI, we need to consider Swift itself, since you cannot use SwiftUI without Swift.

The announcement of Swift at WWDC 2014 was a complete bombshell. Here in Australia, I watch the keynote every year while half asleep since it starts at 3 am. That announcement had me wide awake and bouncing out of my seat with excitement. I was an early adopter and have never regretted that decision.

Many well-respected developers have decided to ignore Swift and they have their various reasons, so let’s go through the ones I have heard:

1. I’m very comfortable and productive in Objective-C

This is not a bad reason and for many people, their employer may insist on the language anyway, but this argument doesn’t work for me. Firstly, I think that there is never going to be the One Perfect Language (with apologies to Chris Lattner) so I am always open to new ideas. And personally, I love learning new languages even if I am never going to use them in production. I feel that this makes me a better programmer overall. And there are vast benefits to Swift - it is a much safer language to write it, it is easier to read and more concise to write, it is just a much more modern language.

2. Swift is too new and changes too much between versions

Swift was new. It is now 5 years old and we are into version 5.2. Undeniably, there have been a lot of changes since 1.0 and many of them have been breaking changes. Swift 3 was especially bad in this respect. But this came with advantages too. As early adopters, we were able to influence the direction of the language. And Xcode was always pretty good about providing a converter to the next version. But either way, since Swift 4, there are supposed to be no more breaking changes, so this is an argument whose time has passed.

3. No ABI stability

ABI stability was a crutch that many people clung to as an excuse to avoid Swift. But unless you were building frameworks for distribution, I don’t see that it was ever a complete deal-breaker. The Swift ABI Stability Manifesto has a good review of what ABI stability is and what it will allow. As app developers, the main advantage is that the Swift libraries will no longer need to be bundled with each app. This will decrease app sizes dramatically. But either way, we now have ABI stability, so again, this argument is finished.

4. Apple may not be serious about Swift and it may not last

I think there was a certain amount of wishful thinking here. The main data behind this theory seemed to be that very few of the Apple apps included any Swift. And in the beginning this was true. I expect Apple’s apps have a rather longer development time-frame than apps produced by independents. However over the last few years, more and more of Apple’s own apps have started to use Swift, either completely or partially. And any doubt about Apple’s commitment to Swift should have been permanently laid to rest by the announcement of SwiftUI.

5. It’s too complicated

OK, this one has some validity, but then again, if Swift is to rule the world, it needs to be able to do a lot of things. I love Swift, I love writing in it and I am very productive when using it. But then I see a chunk of code sprinkled with generics and unsafe pointers and I can’t make head nor tail of it. However, I think that if you are writing any standard, non-arcade-game app, you can write very good Swift using just the basics.

Why did Apple make SwiftUI?

Having demolished the arguments against using Swift, it’s time to move on to SwiftUI. Let’s start with the reasons why something like this had to happen.

Apple now has 5 or possibly 6 user platforms: macOS, iOS, iPadOS, tvOS, watchOS and maybe CarPlay. (I’ve never considered any CarPlay development so I have no idea how it works.) The screen sizes range from 38mm for the smallest watch to over 75” to large screen TVs (apologies for mixing my units there, but it seems that TVs have not gone metric yet). As far as user interface frameworks go, we have had AppKit, UIKit and WatchKit. AppKit is the venerable old member of this team, descended from NextStep (which is why every element name has the NS prefix) and is used to make macOS apps. UIKit was built from scratch for the iPhone and so is a lot newer and neater than AppKit, but at the same time it is more limited. It has never had to deal with the vast variability and complexity of a Mac app’s interface. WatchKit is an even more slimmed down framework with a relatively small number of interface elements.

Now imagine that you are trying to write a multi-platform app. You have to learn at least 3 different ways of doing everything. And there are differences that always catch me out. For example, in AppKit, to set the text in a text field, you set the field’s stringValue but in iOS, you can set the field’s text property. And in WatchKit, you call the setText() method.

Want to change the background color of a view? UIView - no problem, set backgroundColor. NSView - nope - do something weird with layers. I forget what, I have to look it up every time.

These inconsistencies are annoying, time-consuming and a huge barrier to cross-platform development. It really annoys me when I read articles or tweets that assume Swift programming = iOS programming when it is so much more. But before SwiftUI, it was not easy to jump between the platforms.

Catalyst, previously code-named Marzipan, was supposed to be the answer. And it is a partial answer. It allows iPad apps to be ported to the Mac and that’s great for iPad developers who want to expand their reach. But it isn’t the answer for everybody.

Interface Builder

Before I go further into what I think is so great about SwiftUI, I would like to take a moment to discuss Interface Builder. Xcode is a brilliant tool that gets better with every release, but its weak point has always been Interface Builder. I am old enough to remember when Interface Builder was a separate app (not that we called them “apps” in those days) and although it has been folded into Xcode for many years now, the connection between interface and code has always been clunky and un-intuitive. Control-dragging from interface to code and then remembering to switch between Action and Outlet so that you don’t end up naming your button “doneButtonWasTapped”. And if you get the modifier key wrong, who knows what weird stuff will happen.

And then came Auto Layout… It was vastly more flexible than the old school springs & struts and with the ever increasing number of iPhone & iPad models something had to be done, but if you have never ended up swearing at Auto Layout and reverting to a previous commit or mashing Undo repeatedly, then you can’t have used Auto Layout very much!

WatchKit had an entirely different approach to layout and it was easy, intuitive and very refreshing. You drag in objects, they go one under another. You can group them horizontally or vertically, you can make them into table cells. WatchKit has a much more limited set of interface elements and a much more limited set of device sizes to deal with, but I think we can clearly see the origins of SwiftUI in the way it worked. Even if you still had to use Interface Builder to do it.

Interface Builder’s quirks lead to a category of programmers who felt the need to write all their interface in code. To my way of thinking, this is a huge waste of time and you still had to wrestle with Auto Layout, but without the visual clues! But if it makes them happy…

What Is SwiftUI?

A “declarative UI framework” - what does that mean? Basically, declarative programming is a way of specifying what a program should do, rather than specifying how to do it. A common example is making a sandwich. If you want a sandwich, you say to the sandwich maker, “Please can I have a ham, cheese and tomato sandwich”. You don’t say “Get two pieces of bread, butter both of them, cut 3 slices of ham and 2 slices of cheese…". They know how to make a sandwich so you only have to ask for what you want.

Back in the Apple UI world, what if you want a button? Is it for an iPhone app? Then you need an UIButton with a certain type. Set its title, size, location, layout constraints. What are the default sizes for an iPhone button? What is the default font? What color should the text be? Now make a button for a tvOS app? That has to be huge! And what other settings does it have? But the thing is, iOS, macOS, tvOS etc. already KNOW what their buttons should look like. So why not just tell the system “I want a button”? Let the system work out the details and you can get on with the cool app ideas.

The other great benefit of SwiftUI is that when used with the Combine framework, it gives you a reactive interface. There have been various third-party libraries for doing this: RxSwift, ReactiveSwift, ReactiveCocoa, Bond etc, but with Combine, Apple is baking this into the ecosystem, which makes it a lot easier to set up and means that it will stay up-to-date with the operating systems. A reactive interface is one where you can bind a UI element to a piece of data and then when the data changes, the user interface updates automatically. You can even bind both ways so that the user interface updates the data without you having to do a thing. Imagine how much boiler-plate code that can eliminate?

The Good, The Bad and The Ugly

1. The Good

You get a lot of interface for very little code. Making tables is a joy without the masses of boilerplate code needed to set up data sources and delegates. The instant preview in the canvas makes iteration much easier. Being able to create something like a Picker and having SwiftUI render it in one of multiple different styles depending on the platform is magical.

2. The Bad

It’s early days yet and SwiftUI has some quirks and bugs. Sometimes the canvas just stops responding, switching into live mode in the canvas can take a while and of course it is still in beta, so there will be breaking changes to come.

3. The Ugly

It is very easy to build up the Pyramid of Doom where you have multiple levels of nesting leading to the end of your code being a seemingly endless stream of closing curly braces. In SwiftUI, one tends to build from the inside out: make a Text view, embed it in a VStack so you can add another one, embed that stack in an HStack so you can add an Image and so on… But there is an answer: Command-click on one of your outer layers and select “Extract Subview”.

Coding the Layout

Earlier in the article, I spoke about programmers ignoring Interface Builder and laying out the interface in code. I don’t think this is a good approach, so how is SwiftUI different? Firstly, you get immediate feedback of the UI you are coding, so you are not losing that visual benefit of using Interface Builder. Secondly, SwiftUI does much of the layout for you, so you are not hand-coding auto layouts or every last detail of every UI element. So as far as SwiftUI is concerned, I am a convert to programmatic layouts. But if not using SwiftUI, I would still stick to Interface Builder.

Another point to consider here is that developers have long argued that if Apple wants the iPad to be seen as a “Pro” device, there should be a version of Xcode for iPad. One of the problems with this was Interface Builder - it is difficult to see how it could be made to work with a touch interface. But with SwiftUI and iPadOS, is it possible that Apple can make an iPad version of Xcode?

Should you use SwiftUI?

I hope that from my previous paragraphs, you have come away with a good feeling for why Apple made SwiftUI and why it is good for us as developers. Personally, I find it a joy to use even in these early beta stages, but some of the arguments against using Swift, can now be applied again to SwiftUI.

That SwiftUI is very new cannot be debated. It is extremely new and even in the handful of betas released since WWDC, we have seen some breaking changes. It feels quite buggy still but as I am running it in a beta operating system with a beta version of Xcode, it would be unfair to blame all the instability on SwiftUI.

SwiftUI is not yet a complete replacement for UIKit/AppKit/WatchKit etc. There are SwiftUI equivalents for many of the interface elements and I recommend the Gosh Darn SwiftUI site which maintains a list of UIKit equivalents as well as really useful snippets of SwiftUI code. But even when SwiftUI does not have the UI element you want, there are two easy options: use UIKit/AppKit or build your own. Apple has made sure that there is no problem about mixing and matching UIKIt/AppKit code with SwiftUI. And maybe the SwiftUI tools would allow you to build your own version of the missing element. I needed a progress bar and I built one myself with not much code and ended up with what I think is a better look than the standard one.

Click the image for a link to the GitHub repository.

For years, Apple has been telling us to use standard interface elements in our apps and if we did this, when system updates changed the look and feel, we mostly got that change for free. Now they are giving us even more for free by saying effectively, tell us what UI element you want and we will do all the work of configuring it for the platform and for the user’s settings.

But with this, Apple has given us a lot of modifiers we can apply to elements as well as a great animation suite, so I expect to see a lot of more interesting design choices being made in apps, while they are still adhering to all the standard human interface guidelines for the various platforms.

Apple does not promote SwiftUI as “write once, run everywhere” but as “learn once, apply everywhere” and that is an important distinction. It seems at first glance that we can write once but only on a basic level. You are still going to need to design the appropriate UI for a platform, but it will be able to re-use components from the other versions of the same app.

Do I intend to use SwiftUI in my next app - YES. If I was writing code for NASA, I wouldn’t, but my apps are rarely mission-critical, so I can indulge myself and learn as I go. It will be frustrating when there are breaking changes, but at the same time, my bug reports are going to make it better.

One caveat is that SwiftUI apps will require the latest operating systems, iOS 13 and macOS 10.15 so if your app has to support older versions of the systems, you will have to wait until next year. But there is nothing to stop you building some test components and starting the learning process.

To define a tuple, you enclose the data elements in parentheses - normal brackets, not curly or square. Optionally, the elements can have a label attached as shown in the pet example.

Tuples can have any number of components, but if they get too long, a struct might be a better option. SwiftLint will complain if you use tuples with more than 3 elements and usually I go along with that.

There are various ways to access the parts of a tuple. The first way is using index numbers which works but isn’t very intuitive and could be hard to decipher when you come back to a project after some time.

print(pair.0)
print(pair.1)

The next way is if the tuple has used labels for the elements as in the pet example above:

print(pet.type)
print(pet.trained)
print(pet.age)

But the way I prefer to use them is by deconstructing the parts into separate variables in a single statement:

let (x, y, z) = coords
print(x, y, z)

The elements of a tuple can be of different types but once a tuple has been defined, that type of each element is fixed, so you still get all the benefits of Swift’s type safety.

Option-clicking on the variable name shows the inferred type of the tuple:

Trying to re-assign the tuple or any elements of the tuple will only work if the new assignments match the initial types for each element:

Where could you use a tuple and why?

Let’s imagine you have a function that checks a database or web service and comes back with the title of a movie and its rating.

Having got the data, this function needs to return two pieces of data: movieTitle and rating - one String and one Int. How could this be done?

Array: since there are 2 different data types, the array would have to be of type [Any] or the Int could be converted to a String before returning. Neither of these are good options. Using Any removes the protection of Swift’s type safety and converting the Int to and from a String may fail, so then you have to deal with optionals.

Dictionary: the same arguments hold true. The dictionary would have to be of type [String: Any] or the rating would have to be converted to a String.

Struct or Class: either of these would be fine but unless this is a data structure that is going to be re-used, it seems like overkill.

My feeling is that once a tuple is complex enough to need names, you should really consider using a class or a struct, but for returning 2 or 3 chunks of data from a function, this is a very useful technique, espeicialy if the data types are different.

Looping through tuples

If you have an array of tuples, looping through the tuples is made very convenient if you use the deconstruction method of accessing the parts.

As an example, suppose you are dealing with some 3D coordinate system and you want to perform an operation on each location.

You can deconstruct the tuple each time through the loop, assigning temporary variables so you can act on them.

Wrapping Up

So those are the basics of tuples: how to create them, how to use them and where they might be useful. My main use is as a light-weight alternative to a struct for returning multi-part data from a function. But hopefully after reading this article, they have become another tool in your Swift tool belt that you can consider using in certain circumstances.

That leaves only one important question: how do you pronounce ‘tuple’?

I have heard two variations: ‘toople’ using a long U as in universe or ‘tupple’ using a short U as in cup. There does not appear to be any strict geographical differentiation, so take your pick. I prefer ‘toople’ myself, but if somebody says ‘tupple’, I know what they mean.

Thanks

The End of Pic-a-POD

I think I wrote the first version of Pic-a-POD in 2003 and have been updating and maintaining it ever since, but the time has come to shut it down.

I haven’t been able to find a picture of the original version, but here is one from 2005:

And here it is today:

It was written originally as a convenient way to download the daily picture-of-the-day from National Geographic and use it to set the Mac’s Desktop Picture automatically. From there is just grew with more sites added (9 at the moment although I think there have been up to 12 at certain times).

The main issue was keeping up with the site changes of the various sources. Early versions had each copy of the app interrogate the sites directly which meant that any change to the site broke the app until an update could be released. And without the App Store making updates easy to distribute, this was a problem. Later I switched to having PHP scripts on my server do the data retrieval and store the results in a database. The app then just had to request the data from my server. That way if there was a change, I could react quickly and a fix to the server-side scripts allowed all users to get the new data.

As my first Objective-C app and my first app on the Mac App Store, Pic-a-POD has always held a place in my affections, and until last week, it was the one app that was always running on my Mac. So what changed? macOS Mojave’s dynamic desktops! I turned off Pic-a-POD, and set the Desktop picture to change dynamically through the day and I loved it.

On the server, I have kept Pic-a-POD updated regularly, adding and removing sites, fixing the scripts to accommodate changes and so on. But the desktop app has languished and has needed an update for many years now. It’s networking is primitive and I know so much more about programming for the Mac now that looking at the code is positiviely embarrassing! But it has never been a big seller so a re-write is definitely not economically viable, it would only be for my satisfaction. And if even I am not using it any more, what is the point?

So I have made the sad decision to shut it down. But what does this mean for users of Pic-a-POD right now?

Firstly, it is not going away immediately. I will remove it from the App Store, but existing copies are still going to work. If any of the source sites change their data structure, I will not be monitoring this and I will not update the server-side scripts - just turn off that source and carry on with whatever still works. And finally, when the picapod.com domain name expires in 2021, I will not renew it and the app will cease to operate.

What can you use instead? The default dynamic desktops in Mojave are great although there are only two of them, but I have bought myself an app called 24 Hour Wallpaper which includes a great range of dynamic desktop pictures.

So thank you to everyone who has used Pic-a-POD over the years and especially those of you who took the time and trouble to contact me. It has been a fun journey, but there are other apps in my future now.

Moving to the Dark Side - Part 2

Now that most of my Mac apps have been updated to support macOS Mojave’s dark mode, it was time to turn my attention to this web site.

I build this site using Hugo and up until recently I used a theme called Even which I had been able to modify to suit my requirements. The story of how I switched to Hugo, what I wanted in a theme and how I went about, is in a post from last year.

But Evan is a theme with a white background and dark text, which looked great in light mode, but rather glaring in dark mode. So it was time to head for the Hugo Themes page to look for an alternative.

But which way to go? In my opinion, dark themes look better in Mojave’s light mode than light themes look in dark mode, so I decided to go with a dark theme. But to my delight, I found a theme that allowed users to switch between light and dark modes: Hello Friend by panr. Click the light bulb icon in the top right and the web site instantly toggles between modes.

With the spread of dark mode, I would expect more web sites and themes to implement this sort of switching in the future. Thanks to panr for being an early adopter.

As I said in my previous post, I have already updated several of my macOS apps to support dark mode. But after reading some comments on Twitter, I have updated Icon Builder and Dice Pass to allow the user to decide which mode to use. Make your choice in the Window menu as to whether these apps use whatever mode is set for the system, or select your preferred mode.

For A Knight’s Move, I wanted to make sure the wood-look background didn’t change, so I actually disabled dark mode.
For any developers looking for the way to do that, I added the following chunk to the applicationDidFinishLaunching(_:) method:

Swift Strings Helper

Hands up everyone who can remember how to work with Swift strings, especially when it comes to substrings and ranges? ….

Nobody?

Me neither. So I decided that I would work it out once and create myself a library to make it easy for myself in the future. And then I thought that other people might like it too. So I have created my first open sourced project.

Strings in Swift

Swift’s string handling is amazing. It is truly Unicode-compliant, so a Swift String doesn’t care whether your string is made up of basic alphanumerics, accented characters, or emojis that might be composed of several different emojis joined together.

But this power comes at a price, and every version of Swift has changed the way we interact with strings, seemingly making it more and more confusing for the poor programmers trying to stay current. I have got to the stage where each year I read up on the new String features and then promptly forget them. For every use, I have to go back and search how to do what should be simple.

The Problems

To my mind, there are two main problems: indexes and substrings.

In most languages, you can get the n-th character of a string, but not in Swift. In Swift, you have to ask the string for its startIndex (or endIndex), then use an offset to adjust that index by a certain number to give you a String.Index. Do much the same to get a second index and then you can grab the string between those two indices.

To get a sub-string from the 7th up to the 11th character of a string, this is what you have to do:

And now here is the kicker: the results (subStr and sub in the examples above) are not of type String! They are of type Substring so when you go to use them, they don’t work as expected.

I guess there are cases for using Substring but I always just end up casting to String to solve this, but only after the compiler has choked on what I thought was a String all along.

The Solution

To make my life easier, I worked out all the ways that I wanted to be able to split up strings. Basically just two ways: by character number or by substring. Swift already has a substring method but it uses String.Index as shown above. To avoid confusion, I named my functions all sub.

Extras

Once I had created a string helper library, I started thinking about all the other string utilities that would be useful. So I started adding all sorts of facilities:

Computed properties:

length (why should the length of a string be called count - that makes no sense)

words

lines

word count

line count

title case

Encoding:

URL encoding & decoding for queries or forms

base64 encoding & decoding

Trim:

trim

trim left

trim right

trim using extra characters

Pad:

pad left

pad right

with default space or specified other character

That’s as far as I have got so far, but I am hoping for some community involvement that will expand or edit this library to make it more broadly applicable.

Open Source

I have never created an open source project before and I have rarely contributed to open source. But I have now published this library on GitHub under an MIT license. Please check it out at https://github.com/trozware/swift-strings-helper. The GitHub repo contains an Xcode project with all the source files, plus the targets to build frameworks for macOS or iOS, and a playground as documentation and to test it all out.

I would love to get as many stars as possible and it would be fantastic if anyone wanted to log an issue or contribute directly. As someone who finds the whole open source world rather intimidating, I would like to assure everyone that there will be no flaming and no shooting down of ANY ideas. I look forward to hearing from you.

I am sure there are other Swift libraries out there dedicated to solving the same problems, but I hope that mine can prove useful to some. And if you just want to use it without contributing, feel free. The usage instructions are all in the ReadMe on the GitHub page.

Functional Programming in Swift

Search online for any definition of functional programming and you will find many different definitions, few of which are practically helpful. I have no claim to be an expert, but as a Swift enthusiast, this is what I have distilled out of the morass.

What is Functional Programming?

Without providing a concrete definition, here are what I see as the 3 main goals of functional programming:

use pure functions where possible

avoid mutability where possible

use functions as the basic building blocks

So let’s go through those one by one and see how they fit into the Swift language.

Calling the function is now more verbose, but reading the call gives you much more information about what is going to happen. Testing is easy, and the function is completely self-contained so can be copied into any class or struct.

Avoid mutability

This one has become the poster child of Swift Functional Programming as Swift provides some very convenient ways to avoid mutability.

The first is let versus var. My rule is always to start defining any variable/constant with let and only changing to var if the compiler raises an error. In the current versions of Xcode, it will give a warning if you use var unnecessarily which is great, but I still stick to using let first.

The most powerful way Swift lets us avoid mutability with Functional Programming is with map, filter and reduce.

Only names with more than 3 characters and no spaces are considered valid. So this function creates an empty array and then loops through each member of the supplied array and appends any valid names to the new array before returning it.

This function is a pure function and it works as expected. But the validNames array is mutable and there is no need for it to be.

Inside the filter closure delimited by the curly braces after the word filter, (more about closures below), the element in the array being evaluated is stored in the name constant. The checks are done and this implicitly returns a Bool - true if the checks pass, false if they do not. If the closure returns true, the name is valid and will be part of the validNames array.

I recommend the first method even if it is a bit more verbose. Storing the result in a constant before returning it makes debugging much easier. Using $0 instead of using a named parameter is convenient, but I prefer not to do this unless the closure is very simple.

Map

filter takes an array of objects and returns a sub-array containing every element which returned true for the checks inside the filter body.

map changes the elements in an array and can return an array of the same type or an array of different types.

Here is a function to square every integer in an array in the old style, using a mutable array to accumulate the result:

The conversion of String to Int may fail and so returns an optional. If this function had used map instead of compactMap, the result would have been an array of optional Ints: [Int?]. By using compactMap, every nil value was dropped and only valid integers are included.

Reduce

The final tool in the immutability toolbox is reduce and this is one that took me a while to wrap my head around.

Imagine that you wanted to add up all the integers in an array. Here is a way to do it using a mutable variable and a loop:

The reduce function takes 2 parameters. The first is the starting value - in this case it is zero. The second paramter is a function (I am using a closure) this in turn takes 2 parameters and here is where it gets complicated. Inside the closure function, the 2 parameters are the current result and the next value from the loop. And what you return from this closure is going to be the new cumulative value which will either be fed back into the loop, or returned as the final result. The first time through the loop, the first parameter will be the initial value as set in the reduce function call.

To see how this happens, here is a version sprinkled with print statements showing what happens each time through the loop:

cumulativeTotal = 0
nextValue = 5
about to return 0 + 5 = 5 which will become the next culmulative or the final value
cumulativeTotal = 5
nextValue = 3
about to return 5 + 3 = 8 which will become the next culmulative or the final value
cumulativeTotal = 8
nextValue = 8
about to return 8 + 8 = 16 which will become the next culmulative or the final value
final result = 16

Using functions as building blocks

This one is more a matter of style than of any particular programming technique. Basically, keep each function small and break your code into small chunks with obvious naming. This makes your code easier to read, test and debug and it beomes vastly more reusable.

Is it easy to read?
Can you work out what it does? Now imagine all that functionality in a single huge function - would that be as good to use?

As a way of encouraging shorter functions, which leads inevitably to this sort of structured code, I strongly recommend using SwiftLint to check your code. I wrote a post about this a while ago which you might find useful.

Naming

The other key thing to mention and it is a point that Apple makes very strongly, is to name your functions and their parameters so as to make them as readable as possible from the calling site. You write a function once, but you most likely call it multiple times, so it is the calling site that needs to be really easy to read.

Returning to the game example, here is a dummy function to show damage caused to a target:

There are no repeated words in the caller and by using two labels for the second parameter, the calling site can read almost like a sentence, but inside the function, target is still a more logical name.

A third alternative is to use an un-named parameter if the naming logic is implicit in the function name itself:

doCalculation takes 2 parameters. The first one is easy - it is just an integer. The second one is weird! For every parameter of a function, you have to supply the type of that parameter. Usually this is quite straight-forward: Int, String, MyCustomClass etc. But what is the type of a function? Option-clicking on the word cube in my function definition, I see this:

And ignoring the parameter labels, this basically provides the function type: Int inside parentheses for the input, then the arrow, then Int again for the return type. So the type definition for the cube function is (Int) -> Int. And when I define the type for the calculation parameter in the doCalculation function, this is exactly what I put. The last part of the function definition is specifiying the overall return type as an Int.

Using the cube and square functions inside doCalculation works like this:

But what if I didn’t want to define all the functions I might call in advance? Then I can send the function body to the doCalculation function instead of using a pre-built function. This way of using a function inside another function is referred to as a closure.

doCalculation(6, calculation: { number inreturn number *12
})

The doCalculation function in unchanged, but instead of passing it a reference to a function, I am directly passing it the instructions it should use to get the result. As with any function, the instructions are contained within a set of curly braces. The input to this function is listed after the opening curly brace followed by the keyword in. Then the function body does whatever it needs to and returns the result.

You may have heard the term trailing closure. This refers to a function where the last parameter is a function. If that function is called using a closure, there is a short-hand way of writing this, omitting the closure’s parameter name and moving the closing parenthesis to before the opening curly brace.

doCalculation(16) { number inreturn number %3
}

With the filter, map and reduce functions I showed above, this is the way their logic was supplied but here is how the filter example would look without using a closure:

Which methods you use are up to you - they all work. If you have a function that will be called in many different places, maybe it makes more sense to define it once and pass around a reference to that function. If not, a closure has the advantage that it keeps everything together. There is more to closures, particularly to do with variable scope, but I think this post has gone on long enough already…. maybe next time.

World Time in Words iOS Update

Its been a long time since the last update to Time In Words for iOS but after prompting by Apple (update or we will remove it from the App Store), I finally did it. I was never really happy with the last design of Time in Words for iOS, particularly for the iPad, so this was a good opportunity to do a complete re-design, bringing the app more into alignment with its Mac counterpart. And it got a new name to match its new direction and is now called World Time in Words.

In 2015, I released Time In Words v 4.0 for iOS. This was a big change as I had dropped the original QlockTwo concept and switched the emphasis to world time conversions that would be easy to read and understand. This bit worked out well, but the paging interface was not a great success - it made it too tedious to find the zone you were interested in.

The Mac version is a menu bar app that shows the selected time zones as separate menu items. iOS apps don’t have menus, but the closest thing to this is a table, so that is what I went with.

As before, you can add, remove or re-order the time zones and the top three zones can be shown in your Today widgets.

But the feature that I use most in the Mac app is “What time will it be when…". In the iOS app, for reasons of space, the button is labelled “What time will it be?” but the functionality is the same: drag the slider to adjust the hour in your local time zone and see what that hour will be in your selected world zones. This is incredibly useful when you have family, friends and colleagues all over the world and really don’t want to call them at the wrong time of day.

The iPad version of the app is identical at this stage, but I am thinking of adjusting the interface so as to take advantage of the increased real estate. If other work doesn’t get in the way, this may happen…

Privacy Policy

TL;DR: I don’t track you either on my web site or through my apps. If you want to contact me, please do so but I will not initiate any contacts.

As anyone who gets email would realise by now, the EU has introduced a General Data Protection Regulation designed to enhance online privacy. You will have been getting lots of emails announcing new privacy policies or asking you to opt-in to existing arrangements.

So here is my version of those emails (which you will not get by email because I do not store any user data):

None of my apps store data off your device.

I do not have any user data except for data specifically sent to me via web forms, direct email or in-app email.

If you have signed up to beta test one of my apps, you did give me your email address. No tests are currently on-going, but please contact me if you would rather I removed you from any future beta tests.

My web sites are now totally free of trackers and analytics software.

Most of my apps have a “Contact the Developer” button that creates an email that I will answer. If you do not want me to have your name and email address, do not use these buttons.

My web site has a contact page - if you use it, I will see your name and email address and I will respond. Again, if you do not want me to have this data, do not use this page.

Since I no longer have any analytics, I would really appreciate hearing if you find any of my posts useful or interesting.

App Updates

Man Reader

I had to update Man Reader in November 2017 because of a really strange “feature” that arrived with macOS High Sierra. Man Reader displays the man pages as HTML which allows the tabs and internal links to work using anchor tags. These had worked for years, but under High Sierra, they just stopped working.

I eventually discovered that it was because I was loading the text directly into the WebView using:

[self.web.mainFrame loadHTMLString:manText baseURL:nil];

With no baseURL, the anchor links were all defaulting to about:blank and going nowhere. The solution was to save the text to a temporary file and then load using:

Needless to say, this took me ages to work out, including a lengthy excursion into using WKWebView to see if the more modern web view would solve the problem.

The second update (May 2018) was in response to a crash report from a user. I had great difficulty tracking this one down and even now, I cannot see how it can have happened, but it was in relation to the utility apps that are displayed in the toolbar.

For each app, Man Reader checks to see if the app bundle exists, then it checks for a bundle identifier. It appears that this can come back as nil which I had not realised. And trying to insert an item with a identifier of nil into the toolbar caused a crash.

As you can see from the code, ManReader is written in Objective-C. Going back to Objective-C from Swift is painful! And I know that this crash could not have happened if the app had been written in Swift as the identifier would have been an optional and I would have been forced to check that it was not nil before using.

On the plus side, Objective-C apps are tiny in comparison to Swift apps. And the Mac App Store review process set a new record for me. I submitted the app at 10:58 am and it was on sale at 12:03 pm the same day - 66 minutes from start to finish.

Sequenza VII

The other app that I updated recently is Sequenza VII. Version 1.2 was released on 23 April 2018.

This is an app with a very limited audience - specifically oboe players who want to learn to play Berio’s weird music. However Apple sent me a notice saying that as it hadn’t been updated for ages, it would be removed from the store within 30 days unless I did something.

Updating it to use the iPhone X display was surprisingly difficult. I set the minimum system version to 11.0 and changed the storyboards to use the latest Xcode but the horns on either side of the notch were still being left blank. In the end, the trick I found was to create a new Launch storyboard - that seemed to fool the system into re-considering all the layouts.

Consistent Swift Style

What is style in Swift?

Style applies to writing in any programming language and refers to the way you structure your code.

For example, how to you arrange braces?

if theValue <10 {
// do one thing
} else {
// do the other thing
}

or

if theValue <10
{
// do one thing
}
else
{
// do the other thing
}

or anything in between?

Do you use camelCase or snake_case?

Do you always start class names with an uppercase letter?

And of course there is the Great Debate: tabs or spaces? And how many?

Why is important to style your code?

You only write code once, but you & others will read it many times.

As I tell students, in six months time some poor sucker is going to have to read this code, and worse still, that poor sucker might be you, so make it readable.

There is a cognitive load involved in reading code but you can lighten that load by using consistent patterns that your brain can recognise quickly without having to re-analyse them each time.

How do you decide on a style?

Do a search online for Swift style guide and you will get numerous results, although you do have to dodge the sites dedicated to Taylor Swift’s dress sense! I like the Ray Wenderlich guide although its emphasis is on styles that read well in print and in web pages. The LinkedIn guide is also good. GitHub also has a style guide but it hasn’t been updated recently. However it contains some good general advice.

But in the end, you have to decide your own style. The important thing then is to be consistent. I don’t care whether you use camelCase or snake_case, tabs or spaces, but if you use a mixture your code will be harder to read, so pick a style and stick to it.

Is there a way to enforce this style automatically?

This is where SwiftLint comes into the picture. SwiftLint is a tool that can check your code and look for style violations. While it comes with a default set of rules, you can configure these rules to suit your own style.

Installing and Running SwiftLint

To install SwiftLint, I recommend using HomeBrew. Once you have HomeBrew installed, open Terminal and type brew install swiftlint. You can update it any time using brew upgrade swiftlint.

You can run SwiftLint directly from the Terminal. cd to the folder containing your Xcode project and type swiftlint. For a brand new iOS project, you will probably get a result similar to this:

Linting Swift files in current working directory
Linting 'ViewController.swift' (1/2)
Linting 'AppDelegate.swift' (2/2)
ViewController.swift:23: warning: Vertical Whitespace Violation: Limit vertical whitespace to a single empty line. Currently 2. (vertical_whitespace)
ViewController.swift:25: warning: Trailing Newline Violation: Files should have a single trailing newline. (trailing_newline)
AppDelegate.swift:16: warning: Vertical Whitespace Violation: Limit vertical whitespace to a single empty line. Currently 2. (vertical_whitespace)
AppDelegate.swift:44: warning: Vertical Whitespace Violation: Limit vertical whitespace to a single empty line. Currently 2. (vertical_whitespace)
AppDelegate.swift:46: warning: Trailing Newline Violation: Files should have a single trailing newline. (trailing_newline)
AppDelegate.swift:17: warning: Line Length Violation: Line should be 120 characters or less: currently 144 characters (line_length)
AppDelegate.swift:23: error: Line Length Violation: Line should be 120 characters or less: currently 285 characters (line_length)
AppDelegate.swift:24: warning: Line Length Violation: Line should be 120 characters or less: currently 159 characters (line_length)
AppDelegate.swift:28: error: Line Length Violation: Line should be 120 characters or less: currently 218 characters (line_length)
AppDelegate.swift:29: warning: Line Length Violation: Line should be 120 characters or less: currently 141 characters (line_length)
AppDelegate.swift:33: warning: Line Length Violation: Line should be 120 characters or less: currently 155 characters (line_length)
AppDelegate.swift:37: warning: Line Length Violation: Line should be 120 characters or less: currently 194 characters (line_length)
AppDelegate.swift:41: warning: Line Length Violation: Line should be 120 characters or less: currently 128 characters (line_length)
Done linting! Found 13 violations, 2 serious in 2 files.

I have removed the full path that will be listed for each file just to make this fit better.

These reports show the file and line number, whether this is an error or a warning, a description of the error and the name of the SwiftLint rule that caused the warning or error.

You could now go through and fix each of these but there are 2 solutions to make things easier:
Try entering this in the Terminal window: swiftlint autocorrect.

And now if you run swiftlint again you will only get Done linting! Found 8 violations, 2 serious in 2 files. and all the remaining issues are for Line Length Violation This shows that autocorrect cannot fix everything and while it is good on spacing, it has trouble with more complex issues. But it is still worth doing as it can do a lot of the tedious fixes that creep into Xcode projects.

Incorporating SwiftLint into Xcode

The next thing to do to make your life easier is to add SwiftLint to your Xcode project so that it can run automatically whenever you do a build.

Open your project in Xcode and select the project itself at the top of the Navigator on the left. Select the target for the main app and click the Build Phases tab along the top. Click the + button at the top left of the existing build phases and choose ‘New Run Script Phase’. Expand the newly added phase and paste in the following script:

If you think this looks like it is running SwiftLint twice, you are correct. The first time through it corrects what it can and the second pass reports all remaining issues. This is still faster than manually correcting the easy stuff. So now you will see any violations in the Xcode issue navigator when you do a build and you can click the entry to go directly to the code.

Configuring SwiftLint

Now you are all set to SwiftLint all your code, but how do you decide what styles SwiftLint should enforce? Go back to Terminal, make the Terminal window as wide as possible and run swiftlint rules which will return a table like this (click to see full-sized image):

The rule name (identifier) is line_length - this is what appears in the issue navigator or Terminal.

It is not an opt-in rule, meaning that it is enabled by default.

It is not correctable by autocorrect.

It is enabled in this configuration.

And then comes the configuration:

a line of more than 120 characters will generate a warning

a line with more than 200 characters will generate an error and stop the build

this rule will not ignore URLs, function declarations or comments

To set your own configurations, you need to create a .swiftlint.yml file in the same folder as your Xcode project. The leading period makes the file invisible, so you will need to create and edit it using Terminal.

In the Terminal, cd to the folder containing your Xcode project file and run touch .swiftlint.yml to create the invisible file. You can edit the file in Terminal using nano, vim or whatever you prefer, but you can also open it in any text editor. I prefer to use Atom so I open the file by running this command: atom .swiftlint.yml.

The SwiftLint ReadMe has a section about configuration which shows the format and the various general headings you can use, as well as how to configure an individual rule.

opt-in-rules: I went through the list of rules with opt-in equal to yes and enabled all I thought useful.

function_body_length - the default warning length is 40 but I allow myself 60 as that fits on my screen so I can always see the entire function without scrolling.

line_length - with a bigger screen, I lengthen both the warning and error lengths.

cyclomatic_complexity checks for functions that are getting so complex that the compiler might run into trouble. I have this on with the default warning & error limits, but I set it to ignore case statements as they can often trigger this without really being too complex.

Now that my .swiftlint.yml file is edited, doing a build uses those settings and for a new iOS project, I am now down to 2 errors and 3 warnings, all due to long lines in AppDelegate.swift.

The other main way to configure SwiftLint is by disabling specific rules in my code.

As an example, I have an enum for direction:

enumDirection {
case up, down, left, right
}

When I build this, SwiftLint gives a warning:
Identifier Name Violation: Enum element name should be between 3 and 40 characters long: 'up' (identifier_name)

This tells me that up is too short a word to use as an identifier according to the identifier_name rule. In this case, up is the obvious identifier to use, so I want SwiftLint to let it pass. But I don’t want to check my configuration file, because I want it to catch other short identifier names.

The solution is to add this comment to my code, before the case line:

// swiftlint:disable next identifier_name

This tells SwiftLint to ignore the next identifier_name warning or error it sees and now my code builds without error.

Rules can also be disabled or enabled by file. Check out the Disable rules in code section of the SwiftLint ReadMe for more details.

Icon Builder 5

Icon Builder 5.0 is now available from the Mac App Store. This is a complete re-write for better compatibility with Apple’s latest icon requirements. Read on to see what I have fixed and how…

Problems

When I came to create a new iOS app recently, I found out that Icon Builder had fallen behind Apple’s requirements in three ways:

The 1024 x 1024 marketing icon is now supposed to be inside the app’s icon set.

Icon files must have their color profile set to sRGB (P3 is also valid for iOS apps).

iOS icon files must have no transparent pixels and the alpha channel must be removed from the files.

When I set to work fixing these problems I soon ran into issues with the existing version of Icon Builder which was created 6 years ago.

It was written in Objective-C which I am increasingly finding difficult and un-safe to write.

The app was written when I was very much a beginner in Mac apps and this is obvious from the code…

There was a lot of legacy code left over from previous changes and extensions.

So I decided that the most interesting thing to do would be to start almost from scratch and re-write the app in Swift using better techniques.

The Re-write

Now instead of the Massive View Controller, I have a larger set of small files, each with their own responsibility. Enums and structs dictate the various requirements for the different devices or app types. Other structs deal with creating the images, the folder management and writing out the files. An NSImage extension handles the resizing and reformatting of the images. This is now an app that I would not be ashamed to show anyone, except perhaps for the need to add more unit tests.

Adding a color profile

But then we get to the new features needed. Adding the 1024x1024 icon to the app icon set was easy, especially after the re-factoring. But what about the color profile?

This was not as easy as I expected - there is no built in command to apply a profile but here is the solution that I finally found:

This takes the NSImage and converts it to a CGImage, first checking that the appropriate color space exists.

Then it uses the Core Graphics CGImage to create a Core Image CIImage.

There is a new API in macOS 10.13 to extract the png data from a CIImage while assigning a color profile.

This Data can then be written directly to a file and there you have a PNG with an attached color profile.

Transparency

Now problems 1 & 2 have been solved. Problem 3 was the most difficult. It turned out to be a two-part problem because an image file can have no transparent pixels but still have an alpha channel in the file data.

At first, I thought maybe I could just circumvent the whole problem by converting the images to JPEGs which have no transparency or alpha channel. Using the code above, I just changed it to getting the jpegRepresentation instead and saving with a .jpg file extension.

While this solved the alpha channel problem, the transparent parts of the icon just went black which was a not a good look.

For anyone horrified at my use of force-unwrapping, I never do this in a production app but in a playground, it makes the code shorter and it doesn’t really matter if I get a crash there.

Converting transparent pixels to white

So the first step must be to set the transparent parts of the image to another color. Searching for solutions online, most of the ones I came up with were very slow (processing each pixel) or so complicated that I didn’t understand them, and I hate just copy-pasting code that I don’t understand at all.

It used basically the same trick of converting the image into a JPEG but doing it this way via NSBitmapImageRep turned the transparent pixels white instead of black. And as you can see, this gave a much better looking image:

Now I was able to continue with my plans to have JPEGs rule the world! This worked really well in my early tests but then I came to try a Stickers app and the icons didn’t work. I couldn’t even drag them in manually! Back to the Apple docs and I see that icons must be PNGs.

When I changed the transparent pixels to white, added the color space and then saved the PNG data, I got an image that looked correct but the file still contained an alpha channel. So I had to come up with a method that re-wrote the PNG data in such a way that it never contained any alpha data at all.

Removing the alpha channel

Graphics experts are probably groaning aloud by now, but I did eventually arrive at a solution, however hacky:

NCSS 2018

I gave a Masterclass on Swift at the NCSS Summer School 2018 in the University of Sydney on 9th January 2018. This post contains useful links for use in relation to the material covered during my class.

Contact Details

Useful Links

Apps

Mark Time

Mark Time is an application for Celestial Navigation that solves the
problem of how to take an accurate time reading to go with each sextant
sighting. Here is how it was developed…

A day in the life of a software developer - “it would be great if there was an
app that did…”

One of the family is learning celestial navigation and was struggling with the
problem that you either need a partner or more than 2 hands. The key factor is
that you need to record the exact time at the moment when you take your
sighting. And this time has to be in UTC to make your subsequent calculations
work.

Since this is a very simple app, I decided it would be fun to describe the
development process from first specifications to release in the App Store.

The Basic Specs

tap anywhere on the screen to record the time

convert the time to Universal Time (UT)

display that time in a specific format: DD:HH:MM:SS

store the last 5 tap times

A UITapGestureRecognizer over the entire view solved the first requirement.
The native Date object handles time zone conversions perfectly, and then it
was a matter of configuring a DateFormatter with a custom format string to
provide the required date display.

The last 5 times are stored in UserDefaults and displayed in reverse order so
the most recent is always at the top.

UI considerations

colour scheme must work in bright sunlight

text should use dynamic sizing so it works if people adjust the text size on
their iPhones

the UI elements must be out of the way of the new iPhone X system gestures.

while it will most likely be used on iPhones, allow for iPads as well

I had done extensive tests of colour schemes when developing my golf scoring app
19th Hole, so I already had the answer to the colours question: dark grey
background with white text.

Allowing for dynamic type should have been easy - choose a font style e.g. body,
headline, title 1 and set it to adjust automatically. But with a display that is
mainly numeric, the display looked terrible because the numbers in the default
San Francisco are non-proportional. So I switched to Helvetica Neue and watched
for dynamic font size changes manually.

The iPhone X should be fine since I used the new safe area layout guides.

For iPad, I didn’t make a lot of UI changes since I don’t expect it to be used
much, but the display is bigger and probably easier to read.

Refinements

As always, once the first few iterations have been through the testing process,
there were a few things that needed changing and then feature creep set in…

change the date format to be more readable

change the basic tap gesture so that it triggers on tap down, not tap up

add a button to clear all the stored data

display the current time in UTC and in the same format

cheat mode - record latitude and longitude for each time so the calculations
can be checked

change the format for showing the latitude and longitude

sound & haptics to provide feedback

settings

The date format was DD:HH:MM:SS so for 12th December at 1:01:46 pm, this would
show 12:13:01:46 which we decided was a bit confusing. One tended to assume the
first section was actually the hours. Under the new scheme, that same date
displays as 12d 13h 01m 46.654s. The extra precision on the seconds was to show
that the time really was changing if you tapped multiple times quickly.

To make the time record immediately, I removed the UITapGestureRecognizer and
placed UIButtons covering all the relevant active areas. They respond on Touch
Down for a much faster reaction.

Usually, I make a separate View Controller for preferences. This time, because
the app needed access to the standard Settings app for Location services, I
decided to add the app’s preferences to the app’s page in the Settings app. This
worked really well, and made the app itself smaller and simpler.

In cheat mode, the location is recorded at every tap and then the info button
beside each time shows the details. This needed to handle the permissions
required for accessing the user’s location. The latitude and longitude are shown
in decimal format and at first, I also showed them in DMS (degrees, minutes,
seconds) format. I found out that for navigation calculations, they prefer to
see degrees and decimal minutes, no seconds. And rather oddly, this is displayed
something like this: 153° 22’.84 E

Sounds and haptics were added, configurable through Settings. The sound was a
nice loud double-beep designed to be clearly audible to tell you when you had
recorded a time.

Release

After numerous rounds of TestFlight, I was ready to release. The app was
submitted to iTunes Connect and ready for review on Dec 9, 2017 at 7:36 PM. It
moved into review on Dec 11, 2017 at 8:07 AM and was ready for sale on Dec 11,
2017 at 10:19 AM. So less than 39 hours from start to finish of the review
process for a new app - things have certainly changed!

Moving to Hugo

Yesterday, I came to update my blog: I had a new post in draft form and I wanted
to update the Swift code to version 4. However installing High Sierra had
removed Jekyll which is the site generator that I had been using. I
re-installed Jekyll but found that it had been updated from version 2 to version
3.

Jekyll Problems

Then my problems started: missing dependencies due to the basic Jekyll install
no longer including certain features, and then syntax errors due to changes in
the way things are done, particularly to do with pagination.

I tried to fix this myself, then thought that maybe the theme I was using had
already solved these issues so I tried re-installing that. It wanted to add
about 25 more gems and then failed to install - sigh - spend some time rolling
that back…

At this point I decided that if Jekyll was going to cause me a lot of trouble,
it might be worth looking at an alternative.

My main criteria were the ability to import my Jekyll site and the ability to
host on GitHub Pages. After checking out the options, I decided to have a
look at Hugo.

Moving to Hugo

One of the most lauded features of Hugo is speed. I had found with Jekyll that
when I saved an edited page, it took about 5 seconds before the edits could be
reloaded into the browser. Hugo is supposedly fast and does auto reloads.

Following the Quick Start guide, I installed Hugo. Importing my Jekyll site
worked easily and so fast I wasn’t sure anything had happened, transferring my
posts to contents/posts and my other files (status pages, images etc.) to
static.

Then the main exercise appeared to be choosing a theme which would provide not
only the visuals but the capabilities of the site.

So I drew up a list of demands for any theme I chose:

Must Have Features

Responsive

Blog style:

front page with recent posts

tags

archive page

Written using Markdown

Static pages for apps listing, about, contact etc.

Syntax highlighting

Social links

Google Analytics

Would Be Nice Features

Disqus commenting

Twitter cards

JSON Feed

Searching within the site

The Hugo themes page https://themes.gohugo.io has themes listed by capabilities,
but no way that I could see to combine a selection of capabilities.

Some of the features like Google Analytics or Disqus comments, I could probably
add myself using templates from theme that did include them, if the template I
chose did not.

Conveniently, nearly all these seem to come with an exampleSite folder that
contains the configuration info.

Configuring a Theme

After testing out several alternatives, I decided to go with Even - at
least to start with. I installed the theme and copied the contents of the
example config.toml to my own config.toml file and started configuring.

I wasn’t happy with some of the fonts, but soon worked out how to change the CSS
in the theme and then re-build it to apply the changes. And I changed the theme
colour from the default red to “Cobalt Blue”.

Most of the other changes were done using the config.toml file. I was able to
set up menus, configure the social media links I wanted to show, set date
formats, set the number of items to show per page and so on.

I had a couple of more static pages that I wanted to show, so I added their
Markdown files to the content folder.

One nice feature which I had missed in Jekyll (or at least the way I had it set
up) was the ability to separate blog posts from more static web pages. Each of
my apps has an information/support page that does not accept comments and
doesn’t need to be listed in the Archives. By moving these Markdown files from
contents/posts to contents/pages, I was able to achieve this.

Adding Google Analytics and Disqus commenting was as easy as entering my IDs in
the relevant places in the config.toml file.

I had to do some editing of my imported posts from Jekyll - mainly getting rid
of references to {{ site.url }} so that images and internal links would work.
And sometimes I just needed to re-save a file to make Hugo re-evaluate it (there
is probably a command to force a complete re-build if I looked for it.)

Working out the Structure

One thing that I was puzzled by was what templates the various pages are
generated from.

The main page is easy enough as the theme folder has a layouts folder with an
index.html file containing the templating. When a post is displayed, that
looks like it comes from layouts/posts/single.html while
layouts/posts/summary.html contains the templating for each entry in the index
page.

But clicking on the Archives link in the me takes me to https://troz.net/post/
and there is no post.html file in layouts. There is a post folder, but it
contains the single.html & summary.html files described already.

Delving ever deeper, layouts/_default/section.html appears to contains the
Archives page template. But how does that relate to the https://troz.net/post/
link? And the Tags template is in layouts/_default/terms.html but appears in
https://troz.net/tags/. Checking the Hugo documentation for creating a theme, I
find the information I need. Hugo has a selection of file paths that it checks
for such templates, and these file paths match some of those. So now I know
where to go to customise further.

One feature that I really like about the Even theme is the ability to have a
table of contents displayed beside each blog post if your page is wide enough.
It takes the headers in the post and uses them to make the table. I may need to
add or edit the headers in some posts, but I really like this feature.

And if you want a laugh, test out the 404 page - here is a bad link - which
generates a random text emoji each time!

Publishing

I wanted to use my existing GitHub Pages setup, so I replaced the site files in
my local repository with the new Hugo site files. I generated the static site
files using hugo in Terminal, then pushed the pages to GitHub. All I had to do
then was change the settings so that GitHub Pages knew my site was coming from
the docs folder and I was live with the new site.

Final Thoughts

So how am I going with my check list?

Responsive - ALMOST, not Hugo’s fault

Blog style - YES

Written using Markdown - YES

Static pages for apps listing, about, contact etc. - YES

Syntax highlighting - YES

Social links - YES

Google Analytics - YES

Disqus commenting - YES

Twitter cards - NO

JSON Feed - NO

Searching within the site - NO

The Hugo generated pages are all responsive and look great on my iPhone, but my
old static page for listing my apps does not look good, so I need to re-design
that.

Twitter cards - I have found some articles on how to set that up, so it is
possible, but I haven’t done it yet.

JSON Feed is not working. There are themes that apparently have this, but I
haven’t yet worked out how to implement it - hopefully later.

In-site search - this was something I was able to get in my old WordPress site,
but not in Jekyll. There are Hugo themes listed that support search, but they
seem to just give a link to Google or DuckDuckGo. Maybe this can be edited to
restrict it to the site, but I dislike using such searches, so I will not add a
search unless it works internally. One theme I found uses Algolia to search
the site, so I will investigate that.

Overall, I am impressed. The transition was relatively easy, especially
considering that I didn’t take the time to learn anything about Hugo first, but
just blundered in and tried to work it out on the fly.

The speed of generating pages and the live reload while developing make Hugo a
pleasure to work with. Now all I have to do is write some interesting posts…

And I want to tidy up the URLs, headers and tags for the older pages as well as
investigating Twitter cards, search & JSON Feed.

Marktime

Mark Time is now available now from the iTunes App Store for iPhone and
iPad as an assistant for celestial navigators.

Mark Time is an application for Celestial Navigation that solves the problem of
how to take an accurate time reading to go with each sextant sighting.

By simply tapping the screen you can record the exact time UTC as you take your
sight, so you have no chance of making an error with the conversion, and this
time is stored in one of five registers.

Very useful when you have an assistant, and ideal for taking readings when you
are on your own.

As you record a time you hear a confirmation sound and feel a vibration, so
there is no need even to look at the screen. In addition the actual latitude and
longitude at each time can be accessed later to verify your calculations. These
options are all configurable in Settings to suit your own preferences.

Location permissions: On startup, the app will request permission to access
your location. This is how the latitude and longitude data is gathered to
provide this data if you wish.

Support: If you have any questions about this app, please use the Contact
link above to get in touch.

JSON Parsing in Swift 4

Since JSON has become the de facto standard for data transfers around the
internet, there has always been a lot of interest in Swift libraries to parse
JSON into Swift classes or structs. Searching for “swift json library” on
GitHub discovers 77 86 repositories. So why are there so many? And
what has Swift 4 done to sherlock them all?

The problem has always been converting loosely typed JSON to strictly typed
Swift which involves a lot of type casting, checking, optionals etc. Swift has
always provided access to the Objective-C methods for converting JSON to and
from NSData, NSDictionary and NSArray. (These are now called Data, Dictionary
and Array, but those labels are so universal, that I sometimes feel a more
specific nomenclature would be useful. Have you tried doing a search for
‘Data’?)

The first thing to note is that the Swift struct (and its embedded structs) use
multiple different types: Int, String, Double, Address, Coordinates, Company.
The JSON data only has strings and numbers and even then, some of the numbers
are really strings - look at the lat & lng entries. So converting from JSON to a
struct and back again has always been problematic, but let’s give it a go using
built-in Swift 3 processing with no external libraries.

I don’t actually expect you to go through all this code in detail, but I
included it here to make it obvious how verbose this method is.

The first 3 lines get the data, and I have force-unwrapped the URL and the Data
which I would not do in a production app but which is OK while testing in a
playground. Then there is a declaration of the Users struct with all its sub
structs. Each one has a failable init that tries to parse the JSON dictionary
and returns nil if the data doesn’t match, by way of a lengthy set of guard
statements. The basic layout of each struct is the same but it is very verbose.
And as an extra step, the lat and lng properties need to be converted from
Strings to Doubles.

I have to confess that it took quite come time to get this right … lots of
guard statements to check that the data can be converted to the required types
which meant that any typos produced an empty array. The sub-structs have to be
extracted from the JSON as Dictionaries and then initialised by themselves.

Decoding in Swift 4

So this works, and I get an array of Users objects. But it isn’t pretty and it
takes a lot of code to do the processing. So now I am going to move on to doing
this in Swift 4. I am using Xcode 9.0 beta 6 (9M214v) so if you have a later
version, you may need to adapt to any changes.

Ignoring the complexities of converting latitude and longitude to Doubles, I get
vastly simpler code. I declare all the structs as conforming to the Codable
protocol and then I can remove all the init methods and just let JSONDecoder
do its magic. I just have to tell it what data type to expect - in this case an
Array of Users. I don’t have to worry about the initial conversion of the JSON
data to a Dictionary or looping through the elements using flatMap.

In the playground, I used a do…catch structure to check the result of the
decode function, but I have used try? here to keep the code short.

Changing data types

The lat & lng coordinates are stored in the JSON as Strings, but need to be
converted to Doubles for the Swift struct.

This requires a custom init method for the Coordinates struct to do the
conversion from String to Double.

So here is the complete code for Swift 4 - again, if you don’t want to create
your own playground, you can use mine, this time looking at the Swift 4
JSON page:

For comparative purposes, I counted the lines of code in each, removing the
common boiler plate of the top of each and the two lines for displaying the
results in the playground. I also removed the blank lines which I always use a
lot in my code for readability but which are not relevant when comparing code
efficiency:

Version

Lines

Lines if lat & lng are Strings

Swift 3

95

93

Swift 4

35

28

Encoding

Encoding back to JSON is very similar. In the Swift 3 version, I would have
written a method for each struct that created a Dictionary and then used
JSONSerialization to convert the Dictionary back to JSON. This is very verbose
and tedious to write so I am not going to bother to demonstrate it here.

But in Swift 4, this is even easier than decoding. Add this code to the end of
your Swift 4 JSON playground or playground page:

The JSONEncoder returns Data and I have converted that to a String for
checking. I set JSONEncoder’s outputFormatting property to .prettyPrinted get a
more readable String.

Notice how the encoded data is not quite the same as I received because the lat
& lng properties are now Doubles. In a production app, if I needed to be able to
convert back to JSON, I probably would have left them as Strings so as to enable
data transfer in both directions. I would add computed properties to the struct
to convert these Strings to Doubles as I needed them.

Advanced Decoding

Now that we have the basics, I want to look at three more features: changing
property names, date handling and allowing for nulls.

Changing Property Names

In these examples I used exactly the same names for the properties as were used
in the JSON. In the Swift 3 version, it would have been easy to change the
property names, since the data for each property was being extracted manually.
In Swift 4, if you want the decoder to change names, you have to tell it what
you want.

Make a new playground or playground page and replace the contents with this - or
go to the Swift 4 Extras page on my playground:

This uses the new multi-line literals in Swift 4 to assemble the JSON string
which is amazingly useful as it allows quotes to be embedded in the string
without having to escape them. As you can see, the JSON property names are not
very helpful, so I want to change them in my Person struct. At the moment,
person is nil because I have not given the decoder any clues to help it
translate the names. To do that, I have to add a CodingKeys enum to the Person
struct and it tells the decoder what names in the JSON match up to what
properties in the struct.

And that’s all I have to do. Now the JSON is correctly converted to a Person. As
an exercise, use JSONEncoder to get back to JSON from the Person. You will see
that the JSON correctly names the elements using “name1” and “name2”.

Allowing For Nulls

JSON data will often include null where there is no value for a particular
property name. When using JSONDecoder or JSONEncoder, this can be allowed for by
using Optionals. If you are not clear about Optionals, have a look at my
previous article: Learning Swift - Optionals.

The crucial step is to declare the properties of the Swift object as optionals
if you think they could get a null value.

In this example (which you can find in the Swift 4 Extras page on my
playground), I have declared a struct called Role with 3 String properties.
The 3rd String - nickName - is an Optional so it may be a String or it may be
nil.

The JSON contains 2 elements - one has a nickName value and the other has it as
null. Because the matching property in the Swift struct is an optional, this
works as expected and the nickName property for Sally Sparrow is decoded as nil.
If you remove the question mark to make nickName non-optional, the decoding will
fail.

Going back to JSON from a Swift object with optionals works much the same except
that it does not specifically mark items as null, it just leaves them out.

I don’t see this is being quite as useful as the JSON Encoding & Decoding, but I
mention it here for completeness.

Codable

In all the Swift 4 examples above, I set the structs to conform to Codable.
Reading Apple’s docs, I see that Codable is actually a typealias referring to
2 separate protocols:

typealias Codable = Decodable & Encodable

If you only need to convert data one way, it will be more efficient to set your
struct or class as confirming to only one of these protocols. For example, if
you download JSON data from an API but never need to send it back, just conform
to Decodable to transform the JSON data into your data structure.

Posting from my new iPad

Last week I got a 10.5” iPad Pro. I have had an iPad ever since the original
release, but I have to confess to mainly using it for content consumption rather
than creation. Since I am usually close to a Mac anyway, there didn’t seem a lot
of point. But now that iOS 11 is really addressing the issue of making the iPad
a “pro” device, I decided to give it a try.

So here I am, sitting in an armchair with my iPad on my lap, writing this post
and working out the details as I go. Any typos are due to the cat trying to
compete with the iPad for space on my lap!

iPad

As already mentioned, I have a new iPad Pro. I also have an Apple Pencil which I
use for taking notes. I do not have a keyboard, so I am using the on-screen
keyboard right now.

I don’t usually install beta versions of operating systems, but iOS 11 is a huge
part of making the iPad more professional, so I have installed it. As you would
expect, there are a few issues (apps quitting, layout issues especially when
rotating) but so far I am loving it.

Writing

My site is published on GitHub Pages using Jekyll with all the posts
and pages written in Markdown. One key feature is that every post or page
requires a chunk of “front matter” that must be formatted correctly for the
Jekyll parser to interpret it and create the static content. After a bit of
research, it looked like Editorial was going to be the best option for an
editor app. I moved my site files to Dropbox, linked my Dropbox account to
Editorial and I was ready to start writing.

I didn’t want to create the front matter manually for each post. On my Mac I
have a text expander snippet that handles that but copying from Matt Gemell’s
post on the topic, I created an Editorial workflow to create a new post. As
a side-note, Matt has a series of posts on using an iPad which I have found very
useful and inspirational.

Text entry and editing is a task that I have always felt was too difficult in
iOS, particularly when it came to selecting text and moving the cursor. However
there are now several improvements. As with iOS 10, a two-fingered press on the
keyboard transforms it into a trackpad for moving the cursor. If you already
have text selected, this moves the selection handles. The new iOS 11 keyboard
has a really nice feature for entering non-alphabetic characters. The keys now
show a small grey character above the main character. Drag down on the key to
move the small character into the main key and type it. For example, drag down
on the h key to type (.

Editorial has its own editing helpers. There is an additional toolbar above the
keyboard with a tab key as well as frequently used Markdown modifiers. And
swiping across this toolbar moves the cursor. This is a much slower move than
when using the keyboard as a trackpad so might be better for more precise
movements.

Adding Links:

I have referenced a few sites now, so I guess it is time to work out how to link
to them. I always use Markdown’s referenced link method, with the links
collected at the foot of the document, so that is what I plan to do here. To set
text as a link, I selected it and used the Editorial toolbar to type an opening
square bracket which surrounded the selection in square brackets. Then I moved
the cursor to after the closing bracket and typed another opening square
bracket. This auto-closed and I was able to type a number which will be the
reference.

Next step is to find the relevant URLs - drag & drop with multi-tasking to the
rescue! Swipe up from the bottom of the screen to see the new Dock. This also
makes the keyboard disappear. Hold down on the Safari icon until you grab it,
then drag it up into the Editorial window. Now it is open as an overlay.

At this point, I have several options:

Swiping from the left or right of the overlay window lets me position it to
the right or left of the screen, still as an overlay.

Dragging from the bar at the top of the overlap allows me to convert to split
screen mode, and I can then drag the divider to adjust the ratios.

Swiping all the way to the right disappears the overlay, but swiping back from
the right edge returns it. Since I want to copy and paste some links, this
looks like the best option right now.

This swiping conflicts slightly with Editorial’s swiping from the side to see a
preview. Swipe from off the edge for the overlap and from well inside the edge
for preview.

And here my plans come crashing down. I can drag from Safari’s address bar into
the Editorial document, but the drop doesn’t take. I guess I need an update to
Editorial for this to work. But I can still use the old style copy and paste to
get the links.

Images

So now I have my links, but I want to insert a few images. I used iOS 11’s new
screen shot abilities. Press the usual home button & power button combination to
take a screen shot and it appears as a small picture in the bottom left of the
screen. Tap it to start editing: markup, crop etc. Then I used the sharing
button to save the picture to Dropbox, putting it inside the images folder in my
web site folder.

I want to insert an image link but I have just worked out that I saved this
Markdown file in the root folder instead of the _posts folder. I can’t see a way
to move it from inside Editorial, so I will swap to the Dropbox app to move the
file - be right back… (I see now how I could have done this in Editorial.)

Ok, this file is in the right place and the images are in the right folder, so
how to add an image link? Checking back at previous posts, I see that the format
I use for inserting an image is: ![Alt text][#] and the reference at the foot
of the page is like[#]: /images/image_name.jpg but I don’t want to have to
remember that every time, so I think it is time for some snippets. Tapping the
lightning icon on the Editorial keyboard lets me edit and create snippets, so I
have made one for the image link and one for the image reference. Time to scroll
back up the page and try them out.

I opened the Dropbox app in an overlay so that I could find the file names for
the images I just saved, then I created the links. The images don’t appear in
the preview but that is expected because Jekyll has not parsed the addresses.
Looking at the information about the images in Dropbox, I see that they are far
too big. I need a way to resize them. The screen shot editor doesn’t have a way
to resize apart from cropping, at least not in this beta.

Workflow is another Pro level app that I have never really used, but it
seems that it might do the job. I tried a few workflows to edit the size of an
image from a Dropbox file and save it back, but they although they appeared to
complete, the image file remained the same size. So then I went to the Workflow
Gallery and found a workflow called Quick Resize Screenshot. When editing a
screen shot, I can use the sharing button to run the workflow and then I can
save the smaller images to Dropbox for use in the page. For the large images
that I have already saved, I will resize them on my Mac before publishing.

Publishing

This brings me to the final step - publishing the changes to GitHub Pages.
Jekyll is a system that creates static web pages from the Markdown and other
files. on my Mac, I run the jekyll build command in Terminal and the pages are
created or re-generated as required. Then I use git to commit my changes and
push them to GitHub which serves them.

There appear to be Editorial workflows written in Python that use the GitHub
APIs to upload files, but this wouldn’t work well for me. Because of the
structure of my site, many different pages need to be re-generated when I
publish a new post, so I will keep the publishing phase on my Mac. However there
is no need to make it any more difficult than necessary, so I have written a
shell script to do the work.

The script takes an optional commit message parameter, builds the site, commits
changes and pushes then to GitHub. I have only tested this when no files had
changed, so this post will be the first real test. Shell scripting is outside my
comfort zone, so we will have to see how that works.

Summary

So now I have a workflow on my iPad that uses Editorial, Dropbox and Workflow.
This allows me to do 100% of the writing task. Then I have a single shell script
on my Mac that does the publishing part. I can edit and create posts anywhere. I
can easily use split screen or screen overlays to add links. iOS 11 makes
creating and annotating screen shots very easy.

I am hoping for an update to Editorial that will allow it to accept drag & drop.
The ability to resize screen shots before saving them would also be really
useful.

Sometimes my posts are more code-based and need access to Xcode and in those
cases, I will stick to my Mac, especially considering Xcode’s new ability to
connect directly to GitHub which will make it great for publishing Swift
playgrounds. But for more narrative-style posts like this one, I will use my
iPad and see how I can improve my workflow and expand my tool set.

It feels good to be using the iPad as a content creation device at last.

Extra Notes from a Mac:

Since this was my first time writing a blog post using an iPad and this
workflow, I decided that I should test the results before publishing, so I
switched back to the Mac and in Terminal, ran jekyll serve so that I could see
the results. There were a few issues mainly to do with the formatting of the
front matter. The three dashes at the top & bottom of the front matter had
become munged into an emdash plus a dash, so that didn’t work. Jekyll is also
fussy about the spaces in the tag & summary lines and it doesn’t handle
non-alphanumerics in the summary text.

I also used the Mac to shrink some of the images that I had saved before working
out how to reduce the size of screen shots.

So I need to check the structure of the front matter workflow before next time,
but this post is ready to go with only minor editing on the Mac side. Now to
test my shell script…

JSON Feed for TrozWare

jsonfeed.org has announced a new format for web site feeds, designed as an
alternative to RSS. TrozWare has had an XML RSS feed for years, but I don’t
think anyone ever uses it (I certainly don’t), so today I have replaced it with
a JSON feed, which you can access through the
button at the top of every page.

I am sure many JSON Feed viewers will appear soon, but the only one I know about
so far is at http://json-feed-viewer.herokuapp.com. As soon as this update
to my site goes live, I will apply to have TrozWare added to the list of sites
on this page. Meanwhile, you can paste in the URL: https://troz.net/feed.json.

This site is constructed using Jekyll, so I am very grateful to Niclas Darville
for his very easy to follow guide. However it is still well worth reading
through the official specs to see what else you want to add, or if you want
to remove anything. I had to tweak a few settings to make it work for my
configuration, and I added some more objects, but Niclas got me off to a flying
start.

Two things to watch out for:

Make sure your feed is producing valid JSON (I had an extra comma that was
breaking it…).

As third-party apps & sites may be displaying your content, you need to make
sure that you are not using relative URLs for images and internal links. I
was using relative image URLs like /images/WorkHelp1.png but that showed a
broken link in the feed viewer, so I have changed all such links to
/images/WorkHelp1.png. Hopefully that will work correctly on my local test
server as well as when published.

JSON Feed offers a nice icon which I would have liked to use, but I could not
work out a way to make it play nicely with the existing icons on my pages which
all use Font Awesome icons. So I ended up just using the existing Feed
icon. Hopefully Font Awesome will soon add a JSON Feed icon to their already
impressive list.

If anyone still wants to use the RSS feed, it is no longer linked to the
buttons at the top of the pages, but you can access it manually.

Blackmail Marketing

I use my iPad to play games as a form of relaxation. Nearly all the games I play
are puzzle apps with levels that can be played in a few minutes. Nearly all of
them are free to install. So how do they make money?

Now I would be the last person you should consult about marketing but it has
always seemed to me that the best way to market your product is to convince
people that it offers something they want so that they are prepared to pay for
it.

This is not the currently favored approach for mobile apps - at least certainly
not for games. No, the theory at the moment is to cause so much frustration and
annoyance that people give you money to make it stop. Blackmail marketing.

A frequently used method is showing ads, sometimes just banner ads but more
often full screen video ads that run for up to 30 seconds. If you interrupt the
ad, you don’t get the reward.

Every goal reached triggers an ad.

Quitting and resuming the app triggers an ad.

Wanting to play another level triggers an ad.

The theory is that you get so annoyed with this that you pay money to disable
the ads.

The other common tactic is the delay. A tower defence game needs you to build a
tower? OK, that will take 12 hours real time and you can’t proceed until it’s
finished. Or you can spend 12 gems which are sold as an in-app purchase. Maybe
you can only play 3 levels and then you need to recharge: again, pay up or wait.
You keep dying on that level? You’re out of lives. Pay up or wait until
tomorrow. These delays are completely artificial. They have nothing to do with
game play but are solely designed to infuriate you enough to get you to pay.

So when, and perhaps more importantly why, did mobile app marketing become so
negative? What happened to making your customers happy? Do unhappy customers
spend more?

Financially, it appears that irritating your users is a successful strategy.
Nearly all the top grossing games in the App Store are “free to play” in that
the initial download costs nothing. But these big studios are raking in enormous
sums of money, so many people are persuaded to spend significant money by these
infuriating schemes.

A large part of this must be due to the various App Stores driving prices to the
bottom. Gone are the days when the price of a mobile app was other than risible.
So app developers have four choices:

Do it as a hobby or learning exercise.

Distribute apps as a form of self–promotion for other work.

Work for someone who pays you a real wage to develop apps.

Join the blackmailers.

So how does this relate to indy developers like me? I care about my users and
want them to be happy.

I have tried several different approaches to app distribution:

Totally free gets by far the most downloads but is economically ridiculous
unless the app adds value to your business in some other way.

A tip jar gets you nothing.

In-app purchases (in my limited experience) make less than selling the app
up-front for a small price.

Banner ads with no method of forcing people to watch them generate almost no
revenue.

So that leaves me with where I am today - selling apps for a few dollars and
nothing more. Happily, I have found that Mac users are more prepared to pay a
few dollars for an app, so I have shut down many of my iOS apps and am
concentrating on the Mac app market.

Am I letting my principles stand in the way of mobile app profits? Should I just
join the gang and start blackmailing my customers? If so, what form should this
take?

At the moment, I am considering banner ads on the screen with an in-app purchase
to disable them entirely. I read a suggestion for a less invasive method of
doing this by creating your own ads for your other apps. This might be what I
end up doing.

I would welcome any suggestions, advice or comments. Please join the discussion
below or contact me using one of the links at the top of the page.

Useful Links:

Looking for beta testers

Work is a project organizer app for developers, designers, students or any
professional who works with multiple projects involving files & folders, web
pages, email addresses and lists of tasks. Click the link above for more
information and help for getting started.

Work requires macOS 10.12 or OS X 10.11.

If you would like to test this app, please contact me, giving details of
your Mac and operating system. The easiest way to do this is to select About
This Mac in the Apple menu and send me a screen shot of the window that
appears.

All beta testers will receive a free license to Work when it is released. If you
report a legitimate bug or provide valuable feed-back, you will also receive a
free license to your choice of one of my other apps.

Work

Work is a project organizer app for developers, designers, students or any
professional who works with multiple projects involving files & folders, web
pages, email addresses and lists of tasks.

Work requires macOS 10.12 or OS X 10.11 and will be available from the Mac
App Store soon.

We all know what it is like to be in the middle of a project or rushing to
complete an assignment…

We have files scattered all over the place, email addresses of team members or
clients, web pages with specifications or useful information, tasks scribbled on
sticky notes or scraps of paper.

Wouldn’t it be better if there was one place where you could have quick and easy
access to all these items, but without having to change the way you work? With
the Work app, you can regain control - the app helps you get to what you
want so you save time.

Here is the project document you will see when you select Work Help from the
Help menu:

It gathers together some useful links to information about Work and my other
apps or to allow you to contact me. In Work documents for my apps, I
assemble the project files I need to open, images, web page addresses etc. My
most frequently used links are starred so I can focus on them whenever I want a
shorter list.

Drag files or folders into the window to link them to your Work document.
Copy a web address or email address and use Add Web/Email to quickly create
a new link entry with the copied address.

Switching to Tasks mode allows you to focus on your tasks list. Tasks can be
grouped, re-ordered and marked as complete. Use the View menu to hide
completed tasks if you want a more compact list. Use the Edit menu or the
toolbar buttons to edit groups - this allows you to create your own custom
groupings.

Work doesn’t move or rename any of your files - it merely links all these
things together for fast, convenient and searchable access. It even tracks files
or folders if you move them later.

Make a Work document for every project, drag in the relevant files or
folders, add web page addresses and email addresses, make your own task lists.

Create groups to gather items together, adjust the display to view only the
entries you want, use quick look to get a fast glimpse of files or web pages.

Work also supports the Touch Bar on the new MacBook Pros:

Select Work Help from the Help menu to see the special Work document
pictured above. Use the links to keep in touch and step through the sequence of
tasks to learn the basics of using the app.

Another Man Reader Update...

The main reason for this version was that Man Reader was not previously
detecting man pages installed by third-party IDEs in the Applications folder.
There was also an issue with Man Reader failing to display the text of the
previously selected man page on app launch.

More complete search for man pages, including in third-party IDEs.

Fix for glitch when displaying previously selected page on launch.

Man Reader Update

The main reason for this update was to make the app work well with macOS Sierra,
as I found that version 1.6 was sometimes crashing on launch. While doing this,
the update was rejected by the App Store reviewers because it crashed on OS X
10.10. Since I no longer have a Mac running 10.10, I decided to set the minimum
supported system version to OS X 10.11. If you need support for older versions,
you should still be able to download version 1.6 which will work back to 10.7.

I also took the opportunity to fix some graphical issues, dealing with different
color schemes:

The man page list now shows alternating colors even when not using the default
scheme.

When scrolling the man pages past the top or the bottom with a non-white
background, you should no longer see white blocks top & bottom.

Podcasting

I have recently started what I hope will be a weekly podcast with my friend and
colleague, Jerry Daniels. Each podcast will be about 30 minutes in length.

We will discuss Macs, iPhones, iPads, macOS, iOS, programming and anything
tech-related that we find interesting. I hope you will find it entertaining and
informative, so please join us.

We are using ZCast which has an iPhone app that makes it super easy to get
together and record our chats. It doesn’t allow any post-processing, but really
lowers the barrier to entry into the world of podcasting.

If you get the ZCast app for iPhone, go to the ZCasters tab and search for
“Trozware” or “Jerry Daniels” to find all our podcasts. Or use these links to
listen in your browser.

Dice Pass Updated

What does Dice Pass do?

Dice Pass is a utility to app to generate random passphrases based on the
Diceware system. Diceware uses a table of pre-defined words, each assigned
a 5 digit code number containing the digits 1 to 6. The official way to generate
a phrase is to roll 5 dice for each word you want in your passphrase and then
consult the words table to find the matching word.

The resulting phrase uses real words or common abbreviations so it is easier to
remember than a random collection of characters. At the same time, the random
selection of words makes the generated passphrase much more secure as it avoids
the human tendency to pick words with personal meaning.

Dice Pass allows you to select the number of words in your passphrase,
re-generate the entire passphrase any time, re-roll a single word in your
passphrase or set the dice rolls manually for maximum security and randomness.

What’s New in Version 1.1:

You can now select from three word lists in the Word Lists menu:

original Diceware list

Beale list (fewer Americanisms and obscure words)

Diceware 8k list (a list of words that is a whole power of two in length)

How much work does Icon Builder save you?

Icon Builder is a Mac app that takes a single image file and creates all
the different image sizes that you need to make a set of icons for your app:
Mac, iPhone, iPad, iOS Universal or Apple Watch.

Version 4, released 16 September 2016 is available through the Mac App
Store.

What’s New in Version 4:

Added support for iMessage apps and Sticker Pack apps.

Added support for creating Mac .icns files.

Better removal of alpha channel for Apple Watch icons.

Clearer usage instructions in ReadMe files.

iTunes Artwork folders will no longer be over-written with the latest image
files.

Supports macOS Sierra and Xcode 8

While working on version 4 and accommodating all these new icon sets (and
wishing I had the time to re-write the app in Swift…), I counted up all the
icon files that Icon Builder makes for each app type:

App Type

Number of Icons

Mac

10

iPhone

8

iPhone supporting pre iOS 7

11

iPad

9

iPad supporting pre iOS 7

13

iOS Universal

14

iOS Universal supporting pre iOS 7

20

Apple Watch (also requires iOS app icons)

8

Sticker Pack app

11

iMessages app

14

iMessages app Messages extension

9

So as you can see, Icon Builder is doing a lot of work for you. It also names
all the icon files using the expected format, stores them in an concept folder,
creates the JSON file that identifies them all to Xcode and optionally installs
them in your Xcode project automatically. That’s a lot of value for dragging in
an icon and clicking a button!

So next time your designer sends you the twentieth tweaked icon for the day,
don’t get mad. Just drop it into Icon Builder and sit back while it does all the
work. (No need to tell the designer that…)

Change Log:

Sand-boxed version now works just as well as the non-sand-boxed so please
switch back to this version.

This version fixes a problem with sand-boxing permissions potentially not
allowing access to all the installed man pages on your system. This should now
be fixed but if you discover any man pages that are available through Terminal
but not through Man Read, please email me the details and help me make Man
Reader better.

There was also an issue with a previous search being restored after a background
update, even if a new search term had been entered. This has been fixed.

If you previously had downloaded the Man Reader (no SB) version of the app from
this site, please revert to the App Store version which you would have needed to
have bought in order to use the downloaded app. If you bought the app from
Paddle, contact me and I will transfer you to the App Store version.
Neither of these other versions will be supported or updated any more.

Dice Pass Mac Update

I recently got an email from someone who had purchased Dice Pass for Mac
from the Mac App Store but had been unable to get it to run. This person
was using OS X 10.9.3.

I checked the App Store specifications and it showed that 10.9 was the minimum
system requirement, so it should have worked. But going back to my Xcode
project, I found that it was set to a minimum of OS X 10.10.

I tried to re-compile for OS X 10.9 but this failed as the app uses several
features that are not available prior to 10.10.

The minimum system version as displayed in the App Store is supposedly deduced
automatically by the App Store servers from the app’s binary. Somehow this was
incorrect in the App Store, so some people may have bought that app and found
that it did not work despite them having what was listed as a compatible system.

If you bought Dice Pass for OS X 10.9 and are unable to run it, I have two
possible solutions for you:

Upgrade your operating system to at least 10.10.

Ask Apple for a refund since it was their error that caused you to buy an app
that you cannot run.

I have updated the app in the App Store changing nothing but the version number
and it is now showing the correct minimum system requirement. My apologies if
you have been inconvenienced by this error.

Learning Swift - Sets

Sets are the forgotten collection type in many languages, including Swift. I
think most developers use Arrays without really considering the advantages of
using a Set but they have some amazingly useful features that should make them a
part of any progammer’s toolkit.

If you want to follow along with a playground, you can download it here.

What is a Set?

A Set is an un-ordered collection of unique items. That’s it - nothing more
than that. So it is very similar to an Array, but it is not indexed like an
Array and it cannot contain more than one of each entry.

The Array is shown wrapped in square brackets, the Set is shown wrapped in
curly braces. This is just a visual clue and doesn’t really mean anything.
You cannot initialize a set using curly braces.

All the supplied elements of the Array are listed, but the Set has removed
the duplicate “dog” element. This did not cause an error or warning, it just
happened quietly.

When initializing a Set, you must add : Set to distinguish it from an array
initialization. In the example above, I did not specify the data type of the
elements in the Set as the Swift compiler was able to infer this from the
contents. But if initializing an empty array, the data type must be specified.
To check how to do this, I option-clicked on mySet to see what the Swift
compiler thought it was.

So mySet is actually Set<String>. This means that to create an empty Set, you
need to use something like this:

Converting between Sets and Arrays

Sometimes you need to be able to switch between the two. My most recent example
was when I wanted to store data from a Set in a plist. Sets are not property
list types but Arrays are, so I converted the Set to an Array before storing it
in the plist. When reading the data in from the plist, I converted it back to a
Set.

let myArrayAsSet = Set(myArray)
let mySetAsArray = Array(mySet)

One useful side-effect of these easy conversions is the ability to ‘unique’ an
Array in a single line. This may be inefficient for large arrays, but works very
well for small ones. Just be careful if the order of the elements is important
as you cannot guarantee the order of elements in a Set.

let myArrayUniqued = Array(Set(myArray))
// ["cat", "dog"]

Iterating over elements in a Set

As with an Array, you can use a for element in set structure, or you can use
enumerated(). But you cannot subscript a Set.

19th Hole Golf Scorer 3.1

One of the problems with using 19th Hole on the Apple Watch is making the app
show every time you raise your wrist. My solution to this was to go into
Settings (either on my iPhone through the Watch app, or directly on the watch)
and change it to “Resume Last Activity” on wrist raise. This worked fine but as
I usually prefer the watch face to show on wrist raise, I had to keep setting
and re-setting this which was a pain.

But last week I noticed the fine print when changing this setting. In this
screen shot from the Watch app on my iPhone, you can see that “session-based
apps” and “some third-party workout apps” will over-ride the “Show Watch Face”
setting.

I started to research this and found that if an app starts a “workout session”,
then it will become the active app until the session is ended or some other app
starts a session. So I got to work and added a workout session to the 19th
Hole’s Apple Watch app.

When you start scoring a round on the Apple Watch, you will see this dialog
asking if you would like to start a workout:

The workout will be stopped automatically when you have scored the last hole.
You can also use a force-press on the scoring screen to turn the workout off or
on at any time.

This should make the app much more usable as an Apple Watch app, so happy
golfing :-)

My Year With Apple Watch

As the Apple Watch hits its first birthday, there seems to be in increasing
number of bloggers complaining about it. One (which I refuse to link to) titled
“My Year of Hell With the Apple Watch”. I think the article has since been
re-published with a slightly less inflammatory title, but really! Did somebody
rivet the watch to his wrist? If it was so awful, why not just stop using it?

I am a watch nerd and have always loved watches and having one on me. I liked
watches with features and even had a calculator watch at one point although as a
woman with skinny wrists, I found it constantly annoying that watch makers put
all the gadgets into man-sized watches so I was left with the choice of no
features or a watch that looked stupidly large on my wrist.

A few years ago I stopped wearing a watch. I can’t remember now why I did it -
maybe my watch strap broke and it wasn’t important enough to get a new one. I
always had my iPhone to give me the time.

But I ordered three Apple Watches as soon as they were available and myself,
husband and eldest son have been using them ever since.

Here are what I consider to be the best features of the Apple Watch:

Accuracy: It is a fantastically accurate time-piece. Not enough people
give this credit, but we have always been used to clocks and watches that were
inherently inaccurate. Having a device on my wrist that I know to be
perfectly accurate is an amazing thing.

Notifications: this takes a bit of work to get right and with every new
app, you need to assess whether to have its notifications appear on your
wrist. But the wonderful thing is knowing that you haven’t missed anything and
being able to glance at your wrist when a notification arrives and tell -
unobtrusively - whether this is something that needs immediate attention. And
the ability to respond instantly to messages and emails with just a couple of
taps is amazingly useful.

Customisable watch faces: depending on what I am doing, I need quick
access to different pieces of information. When travelling, I can set up a
watch face with multiple time zones. When working, I need a timer. When on
holiday, I prefer one of the more relaxing but less detailed watch faces.

Activity: I am not the world’s most active person so I find the three
rings to be a really good motivator. In fact I just had to stop typing and run
up & down the stairs to get another notch to the blue ring. The goals are not
out of my reach, so I like trying to fill in the rings every day.

Voice commands: being able to send a text message completely by voice when
driving or when my hands are busy is fantastic. Starting a timer, doing unit
conversions and navigating are things I do frequently by voice.

Excellent battery life: I started off having the battery life complication
always visible, but it very quickly became apparent that this was unnecessary.
Right now I have been wearing the watch for about 11 hours and the battery is
at 74%. And charging is so fast that if I did run it down, a 30 minute charge
would get me through most of a day.

The Milanese Loop: best watch band ever.

There are other good features, but I think those are my favourites.

So what don’t I like?

Third-party apps are still a problem. I know. I have published three
myself and sometimes they just doesn’t happen. However this appears to vary a
lot. Some people say they can never get apps to run, even Apple’s apps. Others
say they work but with a long delay. My watch seems to be better than the
average but it is still an issue.

Sketches don’t always get through or can take ages. We thought it would be
a lot of fun to send each other little sketches and so it is, despite our
total lack of any artistic skills. But it loses a bit of impact when you have
to send a message 20 minutes later asking if the sketch has arrived.

The exercise tracking seems to be a bit erratic. If my husband and I go
for a walk together, he comes back with 25 minutes of exercise and I only have
7 minutes. Am I not going fast enough? Are my arms not swinging enough? If it
is very hot and my wrist gets sweaty, I seem to get better numbers - is this
because my heart is beating faster or the capillaries closer to the surface
have expanded? Or is the watch picking up a better signal that way? Either
way, I still like the activity circles, but the green ring frustrates me a
bit.

And what would I like to see in Watch 2 / watchOS 3?

Some sort of always-on display of the time.

A speaker to allow Siri to talk back to me and to play audio.

FaceTime audio calls.

Better support for third-party apps - perhaps open up some private APIs?

Allow developers to create watch faces or apps that told the time.

Allow developers to say that an app should stay as the frontmost app once
opened.

Will I buy Watch 2?

At this stage I would say no. We bought the bottom-of-the-line Sport models
because with version 1.0 of anything, you don’t want to spend so much that
upgrading is ruled out. However these watches are still going great and a lot of
the improvements I am looking for will be in software not hardware.

But 14 months ago, I was waiting for Apple to announce the iWatch as we all
thought it would be called, and saying that I didn’t think I would get one. The
feature list convinced me and I have been delighted with it. So if Watch 2 comes
up with some killer feature that matters to me, then I might have to
re-consider…

Xcode is terrible at renaming projects, so it is a really good idea to have
worked out your app’s name before starting. I would even recommend creating an
app ID in your Apple Developer account and registering the app name in iTunes
Connect. Only once you get to iTunes Connect will the name be checked for
uniqueness. Searching the App Stores is not enough as it does not cover
un-released apps or apps that are not available in your country.

So I set up my app. I was hoping for “What’s My Speed?” but was happy with “What
Is My Speed?".

Next step was to create the project in Xcode which I did using the app name and
manually entering the bundle identifier that I had registered at Apple
Developer. Xcode accepted the name without any warnings and created the default
targets using that name.

In the default unit testing file, the module was defined like this:

@testable importWhat*Is_My_Speed*

which made me think that Xcode was quite happy to have parsed the app name as
required to replace any unwanted characters to suit.

The app was built, passed all unit tests, profiled, analyzed, tested on real
devices as well as the simulators and uploaded to TestFlight.

BARRRPPPP!

What?

(I forgot to take a screenshot but found a similar one online. Thanks Simple
Techs)

I have had experience with TestFlight’s oddities in the past, so I incremented
the build number and tried again, thinking that maybe there had been a
processing issue. Same result.

This started a very frustrating 24 hours as I ran through all the possibilities
I could think of or find suggested on the net. Due to disastrous Australian
internet speeds, especially uploads, each attempt took from 40 - 120 minutes.
About 5 minutes to implement the next idea, 25 minutes upload time, then the
rest waiting for Apple to process the app so I could try again.

Here is what I tried:

Uploaded a fresh build.

Removed Bitcode.

Fixed the code signing identity which was set to iOS Developer for some
reason.

Created a completely blank project with same app name and bundle identifier.

As you can see from this list, I thought it was a code signing or profile error.
Using Apple Configurator 2 (the modern version of iPhone Configuration
Utility), I was able to get the logs from my iPhone and entries like the
following seemed to confirm this:

installd.staging/temp.2LWJ2h/extracted/Payload/What Is My Speed?.app : 0xe8008017 (A signed resource has been added, modified, or deleted.)}```

But when I got to the stage of a completely blank app still failing, I suddenly
thought of the question mark. With the benefit of my preamble to this post, you
all probably got there long before I did, but I got there in the end.

The solution was to remove the question mark from the names of the targets in
Xcode. I had to fix up the module names in my unit testing files, but apart from
that, there were no changes. After this I was able to upload the complete app to
TestFlight and install it on my iPhone.

It is possible that it was the Product Names that were the issue, rather than
the target name as in Build Settings, Product Name is set to be $(TARGET_NAME)
by default but I didn’t test that. Maybe next time…

TL;DR Do not put any unusual characters in your target names.
Alphanumerics and spaces are OK, but I am not sure about anything else.

What Is My Speed?

“What Is My Speed?” is available now from the iTunes App Store for iPhone
and Apple Watch.

If you read my recent blog post on Road Trip Apps you will have realised
that I was working on an app to fill a gap that I discovered in our road trip
app arsenal. So here it is: “What Is My Speed?” for iPhone & Apple Watch.

Track your speed on your iPhone or Apple Watch while driving, bicycling, running
or walking. See your course and altitude at all times.

Optionally set a speed limit and get audible warnings on your iPhone when you
exceed it. Reduce the speed limit to zero or extend it over the maximum to turn
off speed limit warnings.

Designed for easy viewing in all light conditions and with very accessible
swiping to change the speed limit quickly and easily.

If you want more detailed information, tap the info button to see a complete
list of available data about your current location. Altitude and floor data may
not always be available but will be displayed whenever possible.

Your current iPhone settings are used to set the default units for speed and
altitude, but these are easily changed after tapping the info button.

To monitor your speed on your Apple Watch, you need to start the app on your
iPhone, but then it does not have to remain in the foreground. However speed
limit warnings will only be given when the iPhone app is active.

To adjust the speed limit, swipe from side to side. The speed limit indicator
will expand for easier viewing and the speed limit will increase or decrease.
Tap again to shrink the speed limit indicator or leave it for a few seconds and
it will shrink automatically. You can also swipe up or down with two fingers to
adjust the screen brightness for maximum visibility.

Tap the “?” button on the main screen to be reminded of the available swipes.

Location permissions: On startup, the app will request permission to access
your location. This is how the speed, course and altitude data is gathered so is
essential for the app to operate. If you have an Apple Watch with the app
installed, the app will continue to track your speed while in the background so
that the data can be sent to your watch. If you do not have an Apple Watch or
the app is not installed on the watch, your speed will only ever be tracked when
the app is the current foreground app.

Road Trip Apps

Over the past few months, we have done two long road trips: one approximately
4,000 km and the other about 1,800 km. These gave us the chance to try out
various apps for navigation and travel information. We live in Queensland,
Australia and some of these comments may be country-specific.

Navigation

Apple Maps is by far the most beautiful and easy to read. It integrates
perfectly with Contacts (as you would expect). Turn-by-turn directions were
mostly excellent. The biggest downside is that it does not allow you to
specify a route avoiding tolls.

Google Maps allows you to plot a route avoiding tolls… if you can find the
setting. Its traffic reporting is by far the best and it would offer suggested
changes of routes during the trip to get around traffic. The interface is
confusing at times. Turn-by-turn directions were good, although I would have
preferred an Australian voice option.

Metroview has all the maps downloaded which saves on data connection costs and
handles bad connectivity areas better. Its best feature is notification of
speed limits and alerts if you go over the limit, although it gets confused
when on over or under-passes. Another very useful feature is the display of
lanes when approaching highway exits, so you could tell which lane to be in.
Apparently the voice guidance is now more natural but we didn’t try this. The
display is messy and cluttered compared to the others.

We ended up with the following sequence:

Apple Maps for the bulk of the trip.

Google Maps & Metroview (on 2 separate iPhones) in the metropolitan areas and
when about to take a highway exit.

Even then it was amusing to see the apps panic when you took a new road and the
apps assumed you had left the road and were heading through the bush! And at one
point there was a large and official sign saying “Ignore GPS - do not take this
turn” and sure enough, both Apple Maps and Google Maps wanted us to turn down a
little country lane instead of keeping to the highway.

Speed Display:

Apart from the basic navigation apps, we tried a couple of speed display apps.
There are a lot of HUD speed apps out there that project the data on the the
windscreen but they had two problems:

They only worked when it was dark. As soon as the sun got up, they became
invisible.

They required you to place your iPhone flat on the dashboard so even if they
had worked during the day, the iPhone would have got far too hot and
shut-down. (We have a mount that holds our iPhones in front of the air vents
to avoid this over-heating problem. Any mount that sticks to the windscreen
itself leaves the iPhone too exposed to the sun.)

One we stuck with (in non-HUD mode) was Speedometer + HUD. This had a clear
display with a few flaws:

When moving from 99 kph to 100 kph, the display was not re-arranged for 3
digits. Moving from 101 down to 100 fixed it, but as 100 kph is the standard
speed limit, this was a frequent annoyance.

Adjusting the speed limit was too fiddly and difficult even for the passenger.
It would have been impossible for the driver.

It only works in landscape mode which does not always suit the car mounts - we
ended up perching the 2nd iPhone on the unused ashtray.

We also tried Talking HUD but didn’t like it. It worked solely in HUD mode,
so was only useful at night or very early morning. It had voice prompts to tell
you when to change gear but in an automatic car, they were just a distraction
and it was not obvious how to turn them off.

But overall, we found having a speed display app as well as a navigation app to
be the best combination. The audible alerts when you went over speed were very
useful when over-taking or getting up to speed as you could get the information
without having to take your eyes off the road.

Future App Plans:

Having determined that a speed display app is really useful, but not finding one
that suited us perfectly, the obvious next step was to design my own. I wanted
it to have the following features:

clean display, visible in all light conditions

easily settable speed limit

audible and visual over-speed warnings

no HUD mode

Apple Watch component for when you only had a single iPhone and it was
navigating but you still wanted a speed display

Update

Structs vs Classes

One of the big debates among Swift developers is when to use structs and when
to use classes.

Classes are the building blocks of object-oriented programming
but structs as provided by Swift are newly powerful. Structs have been around in
C-based languages for a long time, but Swift has made them more powerful and
given them more features so that they are almost indistinguishable from classes.
So what are the differences and which one should you use?

Where they are the same?

both can define initializers

both can define properties

both can define methods

both can conform to protocols

Where they are different?

classes can inherit from other classes

structs cannot inherit from other structs

classes are reference types

structs are value types

The reference type vs value type difference is where things really get
interesting. Have a look at this example of a class with a single property:

That looks like standard stuff, but what do you think personA's name is now?
If you guessed “Buzz” then you win a prize! (No, not a real prize - pat
yourself on the back.)

This is because when we created the personB variable and assigned personA to
it, we did not assign the VALUE of personA, we assigned a REFERENCE to
personA - actually the address in memory of personA rather than the data
inside.

So now we have two objects and they are both looking at the same spot in memory
for their data. This means that changing the name of personB changed the name
of personA as well.

This time, because we are using a struct, when we assign personC to the new
personD variable, we are actually making a copy of personC and setting the
values of personD to this new copy. So now we can change personD without
messing with personC.

Note that I did not have a define an init for the struct because it creates
one automatically. You can still add one yourself if you want to do anything
different, but you do not have to.

At first glance, you may think that you should now use structs all the time to
avoid these unintended consequences, but it isn’t quite as simple as that.
Sometimes a class is still the best thing to use.

The inheritance capabilities of classes can make your decision simple: if you
need to create a button and want to start by sub-classing UIButton or NSButton,
then your button must be a class, not a struct. This will apply to most user
interface objects.

Apple really wants us to use structs and in the Swift standard libraries, a very
high percentage of the objects are structs. But structs are especially well
suited to a certain subset of objects.

The best explanation that I have found of when to use a struct is the Jeff Trick. Reduced down, the rule is:

If you can overload == to compare two instances of your object, use a struct.
If this doesn’t make sense, use a class.

So use structs for your things: Person, Shape, Brick, Cat. Use classes for
everything else.

I would add one caveat: don’t fight the compiler. If using a struct is giving
lots of errors and warnings, change to a class.

A logical consequence of this is that all structs should conform to the
Equatable protocol.

Extending PersonStruct to make it conform just requires a single function:

Conveniently, providing an == function effectively gives us a != function
for free as you can see from the last example.

There is one final point I would like to make about struct and that concerns
mutating functions. Look at what happens if we include a function that changes
the name property in the struct:

Fix-it is very helpfully pointing out that the method needs to be marked as
mutating for this to work and is showing where this should go. Accepting the
suggestion will get rid of the error and then the name can be changed using this
method.

Learning Swift - Optionals

Today I plan to discuss optionals since they were a feature of Swift that I
found difficult to grasp at first.

What is an optional in Swift?

An optional is a variable of a specified type that can also be nil.

Why does this matter?

In Objective-C, any object type could be nil. If you declared a variable like
this:

NSString *myString;

then myString was set to nil by default.

But this could cause issues, especially as Objective-C does not complain if you
send a message to nil. This could lead to bugs that were very difficult to track
down.

The other big use for nil is when returning from a function which has found no
appropriate data to return. The classic example is when looking for the index of
an element in an array. What should be returned if the element is not found in
the array?

Some languages return -1, Objective-C uses NSNotFound, but you have to know
what each language is going to do. The more logical answer is nil. However if
your function is expected to return an integer, then it cannot return nil
because nil is not an integer.

This is where optionals come in: if the function is expected to return an
optional integer, it can return with an integer with the index of the matching
element, or it can return nil if the element was not found. This is much clearer
and less prone to error.

How does Swift handle optionals?

One of the first things that struck me about Swift was how clean the code
looked, without so many non-alphanumeric characters scattered around. Gone were
all the:

* ; [ ]

But instead, Swift code sprouted:

! ?

What were these?

The key to understanding optionals is to realise that when you declare an
optional variable of a certain type, you are actually declaring a box that can
hold a variable of that type or can hold nil.

Once you grasp that concept, it all becomes much more obvious.

var optionalInteger: Int?

The ? indicates that this is an optional variable. It does not have to be
initialised as it is already set to nil which is valid for an optional variable.
Without the ? this would require initialisation as it would not be valid for it
to be nil.

Setting an optional

Setting the value of an optional variable is just the same as any other
variable:

optionalInteger = 3
optionalInteger = 42

Getting an optional

The difference arises when you need to get the data out of the optional variable
in order to use it. This process is called un-wrapping and it means to get the
variable value out of the ‘box’ it is stored it.

The most obvious way is to use !

let newInteger = optionalInteger!

DO NOT DO THIS!

This is called forced-unwrapping and assumes that the optional variable is not
nil. If the optional is nil, this will crash. In Xcode, when you connect
interface elements from your storyboard to a Swift file, Xcode will use ! like
this:

@IBOutletweakvar startButton: UIButton!

I have to assume Xcode knows what it is doing and the button will be available
when needed, but you should not use ! - it is un-safe. By using it, you are
vowing to the compiler that when it gets to that point, the optional value will
not be nil. There are much better and safer ways of doing that.

Use ‘if let’

funcdoubleNumber(_ optionalInteger: Int?) -> Int? {
iflet integerValue = optionalInteger {
// integerValue is not an optional// and is guaranteed to contain an Intreturn integerValue *2
}
// no integer found in the optional,// so return nil to indicate failurereturnnil
}

These two alternatives (if let & guard) do the same job but in opposite
ways. In both cases, they perform a conditional un-wrapping that may or may not
give a valid result. if let checks if it is OK to proceed. guard checks to
see if it is NOT OK to proceed. Which you use is really a matter of personal
preference and working out what is more logical in each case.

The guard statement is really good for checking data early in a process and
making a quick exit it something is wrong. The if let construct encloses your
success code inside a block and can sometimes leave the failure code a long way
from the check which can make it less obvious. The other potential issue with
if let is the “pyramid of doom” common in early Swift code as demonstrated in
this rather contrived example:

And here is the same function but using guard which allows the inputs to be checked immediately and the function exited if the u=inputs are not valid. For a short function like this, the change is not really significant, but if the function does a lot of processing of the input data, checking first and getting out as soon as possible is more efficient.

In this example, we have defined a SocialMediaAccounts struct that holds
optional Person structs for the various social media outlets. The
socialMedia variable is defined as an optional and then created. A
twitterAccount variable of type Person is also created but contains no data
at the moment.

When assigning the twitterAccount to the socialMedia.twitter property, a ?
is inserted which checks to see that socialMedia is not nil. If it is nil,
then execution of that line stops at the ? and nothing bad will happen.

In the same way, when trying to read back the twitter handle, we chained
together 2 optionals with ?‘s. If either socialMedia or socialMedia.twitter
is nil, that line will not complete. Again this is perfectly safe and the app
will not crash.

All the examples in this article are available in a Swift playground which
has been updated to Swift 4 syntax.

Learning Swift - For-Loops

Loops are a fundamental building block of any program. Doing repetitive tasks
fast and accurately is what computers are really good at and what we humans get
very bored doing. Swift offers several different ways to perform loops, but
today we are going to concentrate on for-loops.

The most basic form of loop is the for-in loop. There are two ways this can be
used: looping over the numbers in a range or looping over the elements in an
array or dictionary.

Firstly, the range:

for x in0 ..<5 { printWithSpace(x) }
// prints: 0 1 2 3 4

I am using a custom print function that allows me to print the results on a
single line for convenience.

This for-in loop uses a half-open range and it is effectively saying:

start with x at 0
print x with a space
add 1 to x
is x still less than 5?
yes - go back to the print stage
no - stop

If we wanted to go all the way to 5 instead of stopping before 5, we would use a
closed range by replacing ..< with ...

for x in0 ... 5 { printWithSpace(x) }
// prints: 0 1 2 3 4 5

These methods work fine if we want to loop through a range of numbers one at a
time but what if we want a different increment? There are several ways to vary
the step.

The 2 variations of stride are analogous to the 2 ways of expressing the range
in the the for-in loop.

stride(from:to:by:) starts with the number in the from parameter and each
time through the loop, increments that number by the amount of the by
parameter. If the incremented number is less than the to parameter, the loop
continues.

stride(from:through:by:) works the same way but continues until the
incremented number is greater than or equal to the through parameter.

Note that the result does not contain the through parameter as the next
iteration would have produced 1.1 which is greater than it. And also
startingNumber did not have to be a variable as it is never actually changed.

Using where makes it possible to step through a loop while conforming to some
conditional:

If you want to loop through an array while also monitoring the index of each
element, you can use enumerated()

let arrayOfNames = [ "Andy", "Buzz", "Woody" ]
for (index, element) in arrayOfNames.enumerated() {
print("The name at index \(index) is \(element)")
}
// prints:// The name at index 0 is Andy// The name at index 1 is Buzz// The name at index 2 is Woody

If your array contains optionals, you can use for case let to test each value:

Some of you may be wondering what happened to the old C-style loops like this:

forvar x = 0; x <5; x++ { print(x, terminator: " ") }

This does not work in Swift 3+: the ++ and -- operators and this style of
loop declaration have been removed from the language. For further details, check
out the relevant proposals at Swift Evolution:

Learning Swift - Generics

One of the nice things about Swift is how clean your code looks. A lot of the
weird characters that pepper the code of other languages has been eliminated: No
more semi-colons, asterisks etc.

But then you are reading somebody else’s code and you find these angle brackets
all over the place and they don’t seem to make sense.

What does this mean?

funcmid<T: Comparable>(array: [T]) -> T

It looks like it is a function to find the middle element in an array, but what
is <T: Comparable> or [T] or even just T? They are describing Generic data
types.

Using the dictionary, I find the following definition for generic:

characteristic of or relating to a class or group of things; not specific.

And that really provides quite a good definition for Swift’s generics too. They
allow you to assign a non-specific data type to a function so that function can
be used for many different data types.

But enough of the theory: by far the best way to understand generics is to
encounter the problem they are meant to solve and then to solve it.

The other day I was processing data to feed to a charting library. I ended up
with an array of CGFloats, but there were too many of them, so I wrote a
function to give me the last x elements of an array of CGFloats:

OK, so largeArray isn’t actually the largest array you have ever seen, but it
works for demo purposes. In my code, I had over 20,000 entries in the large
array and only wanted the last 5,000.

I was completely happy with that until I found another data source where the
data was an array of Ints. Still perfectly chartable using my charting library,
but I could not get the end of the array using my nice function. First thought
was to replicate the function:

A quick glance will reveal that the declaration line was the only thing that
changed. I didn’t have to give the function a new name because the compiler
worked out which of the two functions to use based on the types supplied. So all
I was doing was replacing CGFloat with Int in two places (the
numberOfElementsToInclude parameter remains an Int in both cases).

As soon as you find yourself replicating code and only changing the types of
the data, that is a sign that you need to use generics.

For my first attempt at creating a generic function, all I did was replace the
word CGFloat with T where T indicates some type that will be specified
when the function is called. The convention is to use single letters for generic
types: T for Type, A for AnyObject, Z because you feel like it. The choice
is up to you.

That produced this error:

Use of undeclared type 'T'. Well that seems fair enough… how is the compiler
supposed to know what a T is?

It turns out that this is where the angle brackets come into play. You have to
warn the compiler that this function is going to get a generic type and that the
T is only a placeholder, not a real type. So this version compiles and works -
notice the <T> between the function name and the opening bracket:

You do not have to specify what T is when calling the function, that will be
inferred from the supplied data.

Moving on into more advanced use cases, we have two things to consider:

Functions where the generic parameters must conform to a protocol.

Functions that take generic parameters of different types.

The example function I started with (not mine but I forget where I got it… If
it is yours, thanks you very much) used:

funcmid <T: Comparable> (array: [T]) -> T

Instead of specifying the type as completely generic, it specified that it must
conform to the Comparable protocol. This is because the function body used a
sort() function so the generic function needed to be sure that the elements in
the array could be compared. This technique can also be used to restrict the
parameter types to sub-classes of a certain class.

For a function with more than one generic data type, you need to use more than
one placeholder letter:

Singleton to Protocol

I was driving through the town of Singleton the other day and of course, it
got me thinking about using singletons in my apps. Singletons were a commonly
used pattern in Objective-C programming and appear in many of Apple’s own APIs,
but seem to be increasingly frowned upon in the Swift world.

So what is a singleton?

A singleton is a class that only expects to have a single instance. Think of it
as a global instance of a class. In some cases this makes perfect sense if there
can only ever be one instance of a particular class or if there is a default
variant that suits most cases e.g.

If you are using an object with a property name of “shared”, “standard” or
“default” you can be pretty sure it is an singleton.

And what’s the problem with singletons?

There are probably many different opinions here but I have two thoughts about
this:

They are effectively global variables and global variables can make your code
messy and un-predictable.

If they can be accessed by multiple other objects, possibly at the same time,
then you can get conflicts. These can be handled by clever use of background
queues, but it isn’t easy.

What to use instead?

As I drove, I mused on a singleton that I had implemented recently. It was a
logging utility that allowed any object in my app (mostly view controllers) to
save a new entry to a log file. The basic structure of the Logger class was
this:

When I got to think about how I was using this, I realised that instead of a
Logger object that everything could use, what I really needed was a Loggable
behaviour that I could apply & restrict to the few classes that actually
needed to log events. For me, this was the break-through:

Create a behaviour, not an object.

As soon as I started thinking about this as a behaviour, a protocol became the
obvious solution, so this is what I created:

We run immediately into one of the peculiarities of Swift protocol extensions
which has been very well explained by Caesar Wirth. If I had declared
addToLog(_:) in the protocol, then any class or struct conforming to this
protocol would have been free to over-write this function and provide its own
version. This is not what I wanted here - I wanted every object to use the same
version. So I left the function declaration out of the protocol definition and
only included it in the protocol extension.

To use this behaviour, a class or struct just has to be declared as conforming
to the Loggable protocol:

For my app, I knew that I would want all my NSViewControllers to be able to add
log events, so instead of setting them all individually as conforming to the
protocol, I used this shortcut which extends all NSViewControllers to conform to
the protocol.

extensionNSViewController: Loggable {}

I added this line to the Loggable.swift file where I declared the protocol and
its extension, but outside both of them.

Protocol-oriented programming is a new technique to me, so it really helps when
I can find a practical example of where it solves a problem.

If you are new to POP, I highly recommend the Crusty talk from WWDC 2015.
And this article by Matthijs Hollemans was invaluable to me in
demonstrating the problems with object inheritance that are solved by protocols.

Three Rules for Writing Better Swift

1. Do not use !

Swift uses optionals for values that can be nil. To use an optional value, you
need to “un-wrap” it first, which means getting the actual value out, assuming
that the value exists and the optional is not actually nil.

Optionals are the subject of a complete post by themselves, but for now, I
will just say this: When you use ! you are promising the compiler that you
will make sure there is a real value in that optional by the time it is needed.

If this is not the case, your app will crash as shown in this playground:

Instead of using ! you should use optional chaining with ? or check the value
with guard or if let before use.

One trap to beware of is with Xcode’s attempts to be helpful and suggest fixes
to problems. If you use an optional where it cannot work, Xcode will warn you
that it is incorrect, but the suggested fix will be to insert !

When you see this, do not accept the suggested fix, but use it as a warning to
show that you need to fix the problem properly.

2. Use let, not var

Using constants in C-based languages is a pain. I could never remember the
Objective-C syntax for declaring a static constant, so used to fall back to
using #define for global constants. Inside my objects, all instance properties
were variables, not constants. Inside functions, it was the same.

It doesn’t take much imagination to work out that your apps will perform better
and more securely if values that do not need to change are allocated as
constants instead of variables.

With Swift, this is easy as you just declare a constant using the let keyword
and declare variables using var. The Swift compiler will now warn you if you
have used var where let would do, but I prefer to declare everything using
let and only change to var when this causes an error as shown in this
playground example:

3. Allow the compiler to infer types

With Objective-C and many other languages, you have to tell the compiler exactly
what each variable is going to be: a string, an integer, an object of a certain
type.

With Swift, the compiler is clever enough to work this out for you, which can
make your code much cleaner looking and easy to read.

There are a few exceptions to this rule which are shown in the playground below:

Lines 3 - 6 are allowing the Swift compiler to decide what the type is and it is
choosing valid types: Int, Double, String and UIView.

Line 8 is a case where we do not want the default type, which would be Double so
we need to tell the compiler that this one really should be a CGFloat.

Lines 10 & 11 both deal with an array of Ints. In line 10, the values are
supplied so the type of the array can be inferred. In the second case, the array
is initially empty, so the type needs to be specified in the declaration.

Lines 13 and 14 are the same but with dictionaries instead of arrays.

In each case, it would have been valid Swift to specify the type but why bother?
The more text you enter , the more change of mistake and it leaves your code
looking cluttered.

If you ever need to check what type has been assigned to a constant or variable,
Option-click on it in Xcode and you willl get a popup telling you what it is.

This was going to be five rules, but then I got a bit too verbose so will add
more rules in a separate post.

Configuring Xcode

While not strictly a part of my Learning Swift series, today I thought I would
discuss some of the ways to configure and use Xcode to be a more productive and
comfortable programmer.

1. Editor color themes and fonts:

Step through the supplied themes and find the best one for you. Then click the
‘+’ button at the bottom of the list and duplicate the selected theme. Now you
can tweak it to suit you. Each text category can have its own font and size, but
you can make multiple selections in order to do a bulk change. don’t forget to
check out the Console section too - I dislike the default bold text for many of
the console reports, so always change that.

An editing font should be mono-spaced i.e. every character should take up
exactly the same width on the screen. This makes your code look neater and
neater code is easier to read when you come back to it. I also much prefer a
sans-serif font, but that is a matter of preference.

Menlo is the font used by Xcode as a default, but there are many other options
either in the default installation of OS X or as free downloads. I change every
now and then just to keep things interesting, but my current selection is Fira
Code. I love the way it merges two character symbols into a single
character for faster comprehension.

Look for a font that makes it easy to distinguish the digit ‘1’ from a lowercase
‘l’ and where the digit ‘0’ is different to the ‘O’.

To install and use a new font, download the files and then double-click a TTF or
OTF font file to install it in FontBook. Once the font is installed, you may
need to restart Xcode in order to make it available.

2. Add-ons:

Update: Xcode 8 has removed the ability to run any plugins or to use
Alcatraz, so this sectrion is no longer valid. Instead Apple is offering offical
support for Xcode Source Editor Extensions, so they are the way of the future.

3. Documentation:

Xcode has excellent documentation, but unless you specifically download it, this
will all be accessed online. If you have a bad or non-existent connection, this
can be annoying. Go to Xcode’s Preferences -> Downloads and download all the
document sets you are interested in. They are quite large, but having them local
will be a big bonus.

The other tool I use for documentation is Dash. It supports many languages
and is not just for use in Xcode. I found the Xcode integration plugin was not
very useful as it conflicted with other useful behaviours. So I set up a global
shortcut in System Preferences to search Dash for the selected text. This is
much faster than Xcode’s built-in documentation.

4. Other preferences:

Go through the preference panes in Xcode’s preferences and tweak to suit your
style or your group’s preferred style.

General and Text Editing are important. Text Editing has a second tab for
Indentation which is easy to miss. Indentation styles seem to cause a lot of
heated debate, so make sure you check this out.

Accounts is vital if you are publishing to the App Stores and also makes it easy
to transfer all your develop information from one computer to another.

Fonts & Colors and Downloads are discussed above.

I tend to leave the others set to the defaults.

How do I start to learn Swift?

You can just read this book, especially the first section: “A Swift Tour”, but
you will get more out of it if you follow along with the playground. There is a
link to download the playground from the book which you can use directly if you
are reading using iBooks on the Mac. If you are not, here is the download
link.

You will also need to install Xcode from the Mac App Store. Xcode is
Apple’s IDE and is used for programming Mac, iPhones, iPads, Apple Watches and
Apple TVs.

Swift introduced the playground to Xcode. A playground is a fantastic way to
learn and experiment. You do not need to create a project, build, run a separate
app, install on a device. Code typed into a playground is run immediately and
you can see the results instantly, line by line.

Here is an example of a playground showing the code on the left and the result
of each line appearing on the right.

Once you have gone through the Swift Tour, Apple’s book becomes more of a
reference guide to return to whenever you get stuck. The other way I use it is
to check up on changes made when a new version of Swift is released. As the
language is still rapidly evolving, these can be quite extensive. Once I have
the latest version of the book, I go to the Revision History at the back and
click the links to read about the features that have been added or changed.

Apart from Apple’s documentation, there are a lot of great web sites, blogs and
Twitter accounts out there. There are also useful newsletters that give a weekly
summary of exciting developments.

Here are some of my favourites:

Natasha the Robot - my favourite Swift blogger - sign up for her
newsletter and follow her on Twitter.

Erica Sadun - sometimes a bit too technical for me, but often contains
some really useful snippets. Erica has the distinction of being the first
person outside Apple to have had a Swift language proposal accepted as part of
the open source development process.

Why is Swift so great?

Swift is a new programming language for iOS, OS X, watchOS, and tvOS apps that
builds on the best of C and Objective-C, without the constraints of C
compatibility. Swift adopts safe programming patterns and adds modern features
to make programming easier, more flexible, and more fun. Swift’s clean slate,
backed by the mature and much-loved Cocoa and Cocoa Touch frameworks, is an
opportunity to reimagine how software development works. Swift has
been years in the making. Apple laid the foundation for Swift by advancing our
existing compiler, debugger, and framework infrastructure. We simplified
memory management with Automatic Reference Counting (ARC). Our framework
stack, built on the solid base of Foundation and Cocoa, has been modernized
and standardized throughout. Objective-C itself has evolved to support blocks,
collection literals, and modules, enabling framework adoption of modern
language technologies without disruption. Thanks to this groundwork, we can
now introduce a new language for the future of Apple software development.”

Now I can give you my opinion:

Swift makes for code that is easier & cleaner to read (much more important
than ease of writing).

Swift code is safer code.

Swift breaks free from the out-dated conventions of C-based languages.

When Apple announced Swift at WWDC 2105, I was astounded. That such a major
event could have been kept completely secret was amazing. Then I watched every
video from WWDC 2015 that discussed Swift. Some were beyond me and others I
absorbed. Looking back, I can see that the development of Objective-C over the
past few years was all aimed at getting to this point, especially with the
introduction of ARC and blocks.

At that time, I was deeply involved in an existing Objective-C project and not
able to do much in Swift. But I went through the introduction at the start of
the Swift Programming Language book in iBooks and was able to get some
ideas about how the language worked.

Some months later, I was able to spend time on Swift. As a learning exercise, I
converted an existing Objective-C iOS app to Swift. As might be expected, I
really just wrote Objective-C code using Swift syntax. It took a lot more
learning before I was able to write Swift-y code instead of just translated
Objective-C. In future posts of this series, I hope to enable others to cross
that divide faster than I did.

Now when I go back to an Objective-C app, I feel like I am walking a tight-rope.
When I use an NSArray, NSSet or NSDictionary, I think “How can I tell what sort
of objects are in that array?". When I use an object, I think “What if that
object is nil?". All of a sudden, code that appeared stable now feels random.

One of the big things that people have latched onto with Swift is that it allows
functional programming. I plan several detailed posts on functional programming
in this series. But for now I would just recommend that you not worry about the
distinction between procedural & functional programming. Both have their
advocates and their detractors. Both have their advantages and disadvantages.
Just do what ever works for you and we can worry about this later.

Learning Swift - An Introduction

Welcome to Learning Swift.

This is the first post in what I hope will be an extensive series dealing with
the Swift language. Here are some of the questions I hope to answer:

Should I learn Swift? Why?

Why is Swift so great?

How should I start learning Swift?

I already know Objective-C - how do I convert?

After that, I am planning a series of posts discussing the major differences of
Swift from the view point of an Objective-C programmer and the aspects of Swift
that I found difficult to grasp. Topics covered will include such things:

optionals

closures

functional programming

protocols

generics

I am coming from a background of Objective-C, so many of my posts will be
dealing with aspects of Swift that are not familiar to Objective-C programmers.
I will not assume any Objective-C programming experience, but some features of
Swift that are new to me, will be familiar to people accustomed to other
languages.

So let’s start by answering the first question:

Should I learn Swift?

If you are writing or planning apps for any Apple platform - YES. If not,
wait until Swift is available for the platforms you need to support.

Why?

If you are already an iOS or Mac developer: YES

This is the new language and Apple is very committed to it. Objective-C is not
going away any time soon, but Swift is where it is going to end up, so why not
make the jump now while the language is still in development? You have to accept
that fact that every release of Xcode is going to break your code, but the
automatic re-factoring works very well. And by moving to Swift now, you get the
chance to influence the direction of a new language. How often does that happen?

If you are starting to learn iOS or Mac development: YES

If you have no history with Objective-C, then do not waste your time learning
it. There is still a lot of sample code out there in Objective-C, but increasing
numbers of tutorial sites are using Swift and converting their existing
tutorials to Swift. It will help if you know just enough Objective-C to read it,
but you do not need to know enough to write it.

If you do NOT program for Mac or iOS: NOT YET

Swift went open source in late 2015. This is a big deal and Apple’s plans for
Swift are quite clear. They want Swift to be such a main-stream language that it
is used instead of Java for basic computer science courses in universities. This
was never going to happen unless the language was open-source and
cross-platform. It is now open-source and available for Linux as well as
Mac/iOS. While Apple has not yet released any further ports, I think there
are more on the way for Raspberry Pi, Arduino and other embedded systems as well
as server-side Swift libraries like Perfect. I expect that a version for
Windows will not be far behind.

New Twitter account

I have started a new Twitter account so that I can provide rapid support to
users of my apps. Please contact me @trozware if you have any questions,
suggestions, bug reports or would just like to chat.

I will also be using this account to promote my new Learning Swift series.

Possible issues with Icon Builder & Watch icons

It has come to my attention that there are two possible issues with Icon Builder
3.0.1 when using icons created for an Apple Watch app. Once of them is something
I can fix and the other appears to be a bug in Xcode 7.2

Update: Version 3.2 of Icon Builder is now available in the Mac App
Store. This removes the alpha channel from icons for a watch app.

The first problem is that iTines Connect now requires that the icons for an
Apple Watch app include no alpha channel. This is becoming an increasing trend
with it first having applied to the large icon file you upload directly to
iTunes Connect, then to screen shots. I expect it to extend to iOS app icons
soon, but hopefully Mac app icons can continue to include transparency.

With Apple Watch icons, you are supposed to create a set of square icons and
watchOS or iTunesConnect applies the rounding mask. Presumably this is more
complicated if the icon contains an alpha channel even if there are no
transparent pixels. If your Watch app icons contain an alpha channel, you will
see errors like this after uploading your app to iTunes Connect:

You will probably get this error message for every icon size in the Watch app (8
in total). Until I release a new version of Icon Builder that allows for this
this, I suggest you use this Alpha Channel Remover app.

In your Xcode project, go to WatchKit App Assets.xcassets, select the AppIcon
set, right-click and choose “Show in Finder”. A folder will open containing
eight .png files and one .json file. Drag & drop the .png files into the Alpha
Channel Remover window and click the “Remove Alpha Channel” button. This will
replace all those image files with new versions without alpha channels. To
confirm this, select any of the images and press Command-I to get info. In the
More Info section, you will see “Alpha channel: No”.

You can now submit your app again, but that only solves one of the issues.

The other problem is that you will get a warning about the 44x44@2x.png icon
file.

As you can see in the error message, the icon name (which is set by Xcode) does
conform to the required pattern, and the image is the correct size. This appears
to be a bug in Xcode 7.2 but does not stop you from submitting your app as
it is only a warning and not an error. Presumably this will be fixed in later
version of Xcode. I am running Xcode 7.2.1 and still see this warning.

Change Log:

Much improved searching for available man pages.

Sand-boxed version now works just as well as the non-sand-boxed.

The main feature of this version is that it solves the previous problems with
the App Store version and sand-boxing. This was restricting the number of man
pages listed in Man Reader so I had to release a non-sand-boxed version of the
app to allow for full functionality.

However I discovered that although this gave better results, it was still
missing a lot of man pages. Version 1.5 now queries the man page files in a
completely different way which is listing many more man pages.

If you previously had downloaded the Man Reader (no SB) version of the app from
this site, please revert to the App Store version which you would have needed to
have bought in order to use the downloaded app. If you bought the app from
Paddle, contact me and I will transfer you to the App Store version.
Neither of these other versions will be supported or updated any more.

Using 19th Hole on the Apple Watch

19th Hole for iPhone and Apple Watch version 3 is now available through the
iTunes App Store. This version is a complete re-write to accommodate the
changes in iOS 9 and watchOS2.

The major changes are to do with the way the iPhone and the Watch communicate.
In watchOS1, all the brains of the app had to live in the iPhone, meaning that
every single interaction on the Watch had to be referred back to the iPhone for
processing and the result sent back to the Watch for display. This lead to
communications delays and breakdowns which caused third-party apps to work
sluggishly or not at all. In watchOS2, the brains of the watch part of the app
can now operate inside the watch, greatly reducing the number of communications
needed. As well as that, Apple has now provided us with multiple ways of getting
data to and from the Watch which again improves performance and reliability.

With the 19th Hole, I made the decision to change the method of inputting
scores. The previous version used a slider with plus and minus buttons to adjust
scores. The problems with this were the small target area of the plus & minus
buttons as well as the fact that a slider with more than about 3 divisions was
not useful as a visual indicator.

When watchOS2 allowed developers access to the digital crown, I decided to
switch to using that instead. Now you tap the score box of the player you wish
to adjust and use the digital crown to select a number. I think this will be
easier to use while wearing a glove and hope that it is still easy to read out
doors.

The other suggestion is not to do with watchOS2 but is a general tip for using
apps of this kind. By default, the Apple Watch will always show the watch face
when you raise your wrist. Normally this is the most useful thing, but when
scoring a round of golf, it would be easier if The 19th Hole app stayed at the
front. To make this happen, you need to set to watch to show the last used app
instead of the watch face. This can be set using the Apple Watch app on the
phone or on the watch itself.

On the phone:

Open the Apple Watch app.

Select My Watch from the tabs at the bottom.

Tap “General” and then scroll down to tap “Wake Screen”.

Make sure “Resume Last Activity” is checked.

On the watch:

Press the digital crown to see the app icons.

Find and tap the Settings icon.

Scroll down and tap “General”.

Tap “Wake Screen” and scroll down to make sure that “Previous Activity” is
checked in the “Resume To” section.

Dice Pass for Mac

We live in a world of passwords and passphrases and there is a constant struggle
between having a secure and a memorable password. As a result, many of us re-use
passwords even though we know this is a bad idea.

XKCD had a wonderful comic that illustrated the theory of using a
passphrase composed of words that are easy to remember but with a combination
that made the passphrase very hard to guess. However even when deciding to use a
passphrase like this, it is not easy for us humans to avoid using words that
have meaning for us, particularly when it is something we really need to
remember.

Diceware was developed to solve this problem. You have a set of 5 dice and
a list of words assigned to each possible dice roll for 11111 to 66666. You roll
the five dice and get the matching word from the list. Repeat this for the
number of words you want to use in your passphrase and you have a random phrase
that is hopefully still memorable.

But this sounds like a lot of effort and not something you are likely to do when
faced by a password entry field on a web page. So Dice Pass was written to
do the work for you quickly and easily.

Select the number of words you want in your passphrase and see the phrase
immediately. Keep clicking the “Generate New Phrase” button until you get a
phrase you like. If you feel that the computer is not to be trusted when
generating a random number for the dice rolls, use your real dice and click the
dice to change them to the roll you got. If you get a passphrase that is good
except for one or two words, use the Re-Roll button beside those words to get a
new roll for just that word.

Dice Pass

Dice Pass is available from the Mac App Store and version 3.2 (released 26th September 2018) supports macOS Mojave’s dark mode.

Dice Pass is a utility to app to generate random passphrases based on the
Diceware system. Diceware uses a table of pre-defined words, each assigned
a 5 digit code number containing the digits 1 to 6. The official way to generate
a phrase is to roll 5 dice for each word you want in your passphrase and then
consult the words table to find the matching word.

The resulting phrase uses real words or common abbreviations, so it is easier to
remember than a random collection of characters. At the same time, the random
selection of words makes the generated passphrase much more secure as it avoids
the human tendency to pick words with personal meaning.

The Diceware system was invented by Arnold Reinhold. This utility is not
associated with or supported by Arnold Reinhold in any way, but uses his
techniques with thanks. For more information about Diceware, have a look at the
Diceware Passphrase FAQ page.

The default word list used in this app is a variation compiled by Alan
Beale that removes some of the more obscure words. But you can select the
original Diceware word list or the Diceware 8k word list fromt rh Word List menu
if you prefer to use something different. You can also provide your own word
list file if you prefer.

F.A.Q.

How many words should I use in my passphrase?

Arnold Reinhold recommends 6 words. He used to suggest that 5 was sufficient for
most needs, but as of 2014 has increased this to 6. See the Diceware Passphrase
FAQ page for more details. (Link above.)

How often can I re-generate the passphrase?

As often as you like. Keep clicking until you get a phrase that you can
remember. If you get a phrase where most of the words are good but you would
like to change one or two, you can click ‘Re-Roll’ on individual words to change
them.

Is there a way to check the strength of my passphrase?

There are many password strength checkers on the internet and three of these are
listed below. But always be careful when pasting your passphrase into a web
page.

The theory is that shorter words or abbreviations are easier to remember than
long ones, without compromising security. But if you get a word you don’t like
or think that you will not be able to remember, just re-roll that word.

What if I want to roll the dice myself?

Dice Pass allows you to tap on the 5 dice to set the numbers needed for each
word manually. Each time you tap the number will go up be one, wrapping from 6
back to 1. The app will then look up the word table for you and show the new
word.

When the phrase gets too long I can’t see all the words.

The “Copy” button will copy the complete passphrase even if it is not all
visible. You can also scroll by clicking and dragging along the passphrase.

Does my passphrase get saved by the app or transmitted over the internet?

No. The app saves no data except for basic preferences (window positioning &
size, preferred word list etc.). There is never any data sent over the network
and the app will work perfectly if you disconnect your computer before using.

What are those 3 buttons: #, A and 1?

Some sites may require a passphrase that contains a mix of character types.
These buttons will insert a special character, change the start of one word to
uppercase, or insert a number. Tap the button again to undo the change. Again,
these characters are chosen using the dice roll system and the special
characters are selected and positioned using the method and data suggested by
Arnold Reinhold.

I thought there was a version of Dice Pass for iOS!

There was, but with the need to update apps to support iOS 10, I decided to drop
support for some under-performing iOS apps. If you bought the iOS version and
would like to switch to the Mac, send me a screen shot of the app running on
your iPhone or iPad and I will send you a free promo code for the Mac version.

Apple Watch First Impressions

I realise that every one has written one of these posts, but given that everyone
looks for and notices different things, I think it is still valid.

My first impression was “Why does it come in such a large box?". The courier
delivered two boxes - my 38mm Apple Watch Sport and Tim’s 42mm Apple Watch
Sport. They both came in long boxes, with the 42mm box significantly longer. And
both boxes were heavy!

Un-boxing:

Opening them was a typical Apple experience: pull the tag to open the external
cardboard box, lift out the white internal box. This opens to reveal the watch
with the default strap attached (short for 38mm, long for 42mm). Lift the watch
out and pull the tags to remove the plastic protective coating. (On a side note,
it drives me crazy when people leave this coating on devices, but I can’t see
this happening on the watch.) Underneath there is a sleeve containing the other
half watch strap so you can swap from long to short. My family tells me that
this also includes a user guide, but I didn’t read that - typical Apple user…
Under the sleeve is the power block and charging cable. The charging puck is
larger than I expected and the cable is very long. Having removed all the
components, the packaging is still quite heavy, so I guess Apple just wanted to
make sure that no watches were damaged in transit and that it felt like a
quality product.

Pairing

Pairing my watch to my iPhone was amazingly slick. After selecting my language,
the watch displayed a sort of nebula pattern. On the iPhone, I launched the
Apple Watch app, selected the pairing option and pointed the phone camera at the
watch display. This did the pairing. Then I waited while all the relevant apps
transferred their Apple Watch components to the watch and I was ready to start
using it.

The Watch:

The watch comes with the modular watch face showing by default. This is a
digital time read-out with various ‘complications’. Force-touch the watch face
to change it - this takes a surprisingly strong touch. Then you can swipe
sideways to select a watch style. Once you have a style selected, some of them
offer further customisations: select how much detail is shown, choose what extra
information to display, adjust colors.

This is a lot of fun and I am still changing mine very frequently. The good
thing is that your customisations are stored, so if you set up the utility watch
face in a particular way, then swap to the modular and configure it, when you go
back to utility, your previous settings are all still there.

The screen is gorgeous - very crisp and easy to read.

Twisting your wrist to show the time works well most of the time. There is a
delay that I would estimate at about half a second, presumably to avoid false
positives triggering unnecessary displays. If you are holding your wrist at an
unusual angle e.g. showing the watch to someone, this twist will not always
work, but tapping the screen will display the watch face instantly.

Tapping on a complication will take you to the relevant parent app e.g. tapping
the current temperature will open the Weather app.

A minor quibble is that the phases of the moon are displayed from a northern
hemisphere point of view and do not match what we actually see here in
Australia.

Battery Life:

This is a complete non-issue. On my first day with the watch, the battery was at
70% when I first turned it on. As you can imagine, usage was very intense that
first day and I got to 8%. Since then, the battery level has only got down to 40
-50% over a day and it recharges to 100% within 2 hours. Tim’s 42mm model gets
slightly better battery life as expected.

I started off having the battery indicator as one of the ‘complications’ on my
watch face, but now I just ignore it.

And the battery life of my iPhone has improved remarkably due to so many quick
transactions being done through the watch instead.

I did have a charging problem one night. I woke up and checked the time and
realised that the watch was quite warm to the touch. I checked the battery level
which was actually lower than when I had put it on the charger. I took it off
the charger for a few hours, then put it back and all was well.

Notifications

Here is where you need to be careful. I had turned off most notifications on my
phone before getting the watch, so I have not been inconvenienced, in fact I
have been able to re-enable many notifications as they are no longer so
intrusive.

At first we thought some notifications were not getting through to the watch,
then we found out that if your iPhone is awake and un-locked, notifications are
not passed on to the watch. So drop the time until sleep on your phone to the
minimum which saves your phone battery and makes sure you receive most
notifications on the watch.

If you want to stop any apps sending notifications through to the watch, this is
easily set in the iPhone’s Apple Watch app.

I have noticed there is a bit of a delay. I hear an email or message arriving on
my phone and it can be half a minute before it gets to my watch.

Once you get a notification, you can tap it to go to the parent app, swipe up to
process it in some way depending on the type of notification, or swipe to the
left to see a button that will clear the notification. If you want to get rid of
all your notifications at once, do a force-touch on the notifications screen to
get the option to clear them all.

Glances

Glances are designed to be one screen indicators giving you important
information as quickly as possible. From there, you can decide whether to go to
the parent app or not. These are accessed by swiping up from the bottom of the
screen when looking at the watch face.

I found that the most important thing here was to reduce the number of glances
shown, since they are displayed sequentially. If you have 20 glances installed,
you have to swipe at least 20 times to see them all. So go to the Apple Watch
app on your iPhone and turn off the glances you do not find essential.

The first glance in the sequence is essential though as it allows you to toggle
airplane mode, do not disturb and silent mode. It also has a button that can
make your iPhone make a sound to help you locate it. Hold this button down to
make the iPhone flash come on as well.

Activity

Here I have to confess to my first disappointment. The activity app tracks three
things: Move, Exercise and Stand. When you first start the watch, you tell it
your age, sex, weight and height. It computes a suggested daily move goal for
you which you can adjust at any time. Then it tracks your daily activities and
shows how well you are doing in relation to your goal. For exercise and standing
the goals are 30 minutes exercise and standing for at least one minute in an
hour 12 times though the day.

The move tracking seems to be fine. I am not sure what metrics it uses, but on
more active days, the numbers go up.

The exercise one doesn’t work for me. We went for a walk and when we returned,
Tim’s watch showed 25 minutes exercise and mine showed 1 minute. We had walked
the same distance at the same speed, as confirmed by the pedometer. Subsequent
tests revealed that I don’t swing my arms enough when walking to trigger what
ever sensor this is using. I can’t quite see why it ignores the pedometer
completely, but hopefully this can be fixed by a software update. For now, I
just ignore this circle.

Standing is another issue since I use a standing desk, so I stand for many hours
each day. Even when standing, I get my hourly reminders to stand. However I use
this as a trigger to make me to move about for a minute, so I suppose that is
still useful.

Communications

The various forms of communication are a real strength of the watch. With Tim &
I both having watches, we can phone, message (audio or text) and use the new
Digital Touch to send sketches, taps or heart beats. While it feels a bit weird
to be talking to your wrist, this works really well and the sound quality is
amazing for such a small device. If you need more privacy, it is very easy to
transfer a phone call back to your phone.

Oddly, the watch does not appear to offer FaceTime but always uses standard
phone calls.

Messages are where the watch excels. If you get a message with a question, the
watch can suggest possible answers so you just have to tap a button. Even
without this, there is a set of pre-defined answers which you can edit in the
Apple Watch app on your iPhone. And you can also use dictation or the new
animated emojis. Dictation seems a lot better on the watch than it ever was
before on the phone. And even if dictation is not transcribed perfectly, you can
send the message as an audio recording instead of text.

When recording, tap the Done button as soon as you have finished speaking. The
inclination is to wait for the text to be processed, but the recording carries
on, so stop the recording and let the text processing finish in its own time.

The animated emojis work when you send them to other devices as they appear as
GIFs. You can choose from 3 sets: faces, hands and hearts. Once you have swiped
to select a set, use the crown to scroll between the options. You can also swipe
further to get to the standard emojis.

Digital Touch works between watches only. It is a fun gimmick and I can imagine
us developing a set of key codes or sketches, but neither of us can draw very
well, so the sketches are very rough. The heart beat is amusing, but the tapping
is surprisingly effective as an attention-getter.

Summary

I think this is the start of a new way of interacting with our technology in a
way that is both closer to us and less intrusive. I am loving the watch so far
and can’t wait to see where it goes from here.

Time In Words 4.0

Time In Words for iOS started off as a fun gimmick, emulating the
Qlocktwo type of time display where the relevant words are highlighted in
some way to spell out the time as a sentence. This very quickly evolved into
what I hoped would be more useful app, still showing the original display, but
also providing the current time & date as complete sentences. Then I added time
conversions and discovered the real power and utility of writing out times as
words.

When it comes to converting times, I doubt there are many people in the world
who haven’t had problems.

Is that morning or afternoon for them?

Are they in tomorrow, today or yesterday?

What if they are using daylight-savings?

Having the time written out removes all ambiguity. As an example, Time In Words
currently reports very clearly:

In Los Angeles, it is nine minutes to ten on Tuesday evening (daylight-savings
time).

When writing Time In Words for Mac, I focussed immediately on the time zone
conversion facilities, and provided a menu bar app that can display as many time
zones as you like (although more than will show on a single screen would
probably get annoying).

So when I decided to do a complete re-write of Time In Words for iOS, the
obvious move was to emulate the Mac version and allow for as many time zones as
the user wants, instead of the current 2 or 4 (iPhone or iPad). So I discarded
the Qlocktwo display and the separate date display which used a similar
mechanic. I kept the display that shows the current date and time, but every
display after that shows the time in a different time zone. The time zones can
be changed and re-ordered, so the ones you need most are the fastest to get to
once the app opens.

One new feature (again taken from the Mac version), is the ability to calculate
“What time will it be…”

You dial in your local date and time to see what time that will be in your
selected zone. And if you want to calculate the other way around, tap the “Swap
time zones” button.

The main impetus for a re-write was the Apple Watch. I thought this would be a
perfect app for the watch as it could use the Apple Watch’s superb time-keeping
in conjunction with my text generation, to add a significant level of usability
to the Apple Watch as regards time zone conversions.

Sadly, Apple disagrees…

I completed the app and submitted it to the App Store for review. The review
process seems to be very fast at the moment and the app moved into review only
one day later. And there it stuck for 3 days. This was very odd. My experience
is that once an app gets into review, it only takes a few hours, if that. For
19th Hole - my other app with an Apple Watch component, the review process
took 30 hours. But 3 days!

Then I got a phone call from Apple where a very polite person explained to me
that although this was not mentioned in any of the documentation, the marketing
people had decided that no apps were to be allowed on the watch if they told the
time.

I offered to remove the initial screen telling the local time, so the app would
not actually supply the current time but only the time conversions, but that was
not acceptable either.

Then I tried appealing the rejection. My hopes were not high, but I didn’t see
any harm in asking. I again offered to remove the local time display and
emphasised the accessibility advantages of displaying times in this manner.
Another day, another phone call, another polite Apple person saying no.

So now I have re-submitted the app for review without the Apple Watch component,
which is a shame. I am hoping that after some months they will review this
policy and allow me to try again, but who knows.

So you can see what you are missing, here are a couple of screen shots from the
watch app showing my local time, plus one time zone:

One more minor point. People who actually look at version numbers may wonder why
I have gone from version 2.5 to version 4.0. When I was working on version 2.5,
I considered making it version 3.0 and then changed my mind. However by that
time I had already created a version 3.0 in iTunesConnect, so I was not able to
use 3.0 again this time. This version was such a big change that I wanted it to
be a .0 release, so that meant going to version 4.0

Apple Watch App - Rejected, then Accepted

As described in a previous post, about 9 days ago I submitted my first
Apple Watch app for review. The app was an extension of my golf scoring app:
The 19th Hole.

I expected that App Store review times would go up dramatically once Apple had
allowed developers to submit watch apps, but this proved to be incorrect. Three
days after submission, the app was marked as “In Review”. This seemed to happen
last thing on a Saturday, so there was no further action for two days, at which
point the app was rejected, with the following details (sic):

We noticed an issue in your app that contributes to a lower quality user
experience than Apple users expect. Specifically,

while using the Apple Watch app with the phone app is in the background mode
(display off), the new data entry on the Watch App does not refresh
accordingly until the phone app is turn back on.

So it appeared that the communication between the watch and the phone, which
worked perfectly on the simulators, did not work at all on the actual devices.
This is the problem with developing for a device that you do not have.

After some research, it appears that the problem is with the phone not operating
correctly in background mode. Apple provides for communications from the watch
to the phone. The phone can respond, but only the watch can initiate a
connection. I guess this makes sense since every watch will be paired with a
phone but the reverse will not always be true.

The name of the WatchKit function is slightly misleading as it does open the
parent application, but only in the background. Then the parent app is supposed
to do whatever tasks are called for in the handleWatchKitExtensionRequest
function, and return any required data using the supplied reply() function.

So far, so good, and it all worked perfectly in the simulator. But it appears
that although this call wakes the iPhone app, it does not stay awake long enough
to do anything. Many thanks to Brian at Five Minute WatchKit who pointed
out the way to make this work. Firstly, you create a dummy background task
guaranteed to keep the iPhone app awake for 2 seconds. Then you perform your own
work, using another background task. When that is finished, the phone can send
the response and end the real background task. The dummy task will time out by
itself after 2 seconds.

For my needs, I could probably reduce the 2 seconds considerably, but since this
is a problem I am unable to test, I decided just to go with Brian’s suggestion
as it is.

I re-submitted the app the same day it was rejected, and two days later it was
back in review. The review process took longer than usual, but about 30 hours
later, the app was marked “Pending an Apple Release”. I assumed this meant that
Apple would release all WatchKit apps on 24th April when the watches shipped,
but the following day the app was reported as “Pending Developer Release” (I had
set it to release manually). Now I have told iTunesConnect to release the app
and it is “Processing for App Store”.

On a related note, the start of pre-ordering for the Apple Watch was scheduled
for a very civilised 5:01 pm here in eastern Australia. I had three watches all
lined up in my Favorites in the Apple Store app, ready for ordering. When the
store became live (at about 5:03 pm), I could not work out how to order all
three in a single operation, so had to place these orders one at a time. I got
the first two ordered for the soonest possible delivery, but by the time I got
to the third (about 3 minutes later), I had missed out and it will ship in 4 to
6 weeks!

My First Apple Watch App

I have just submitted my first Apple Watch app to the iTunes App Store. This is
a scary thing to do, since I have never seen, touched or used an Apple Watch and
all I had to go on was the Simulator that Apple supplies with Xcode.

At the moment, Apple has only made a limited set of Apple Watch features
available to developers, and all Apple Watch apps come tethered to an iOS app -
presumably this will mainly be iPhone apps, but I wonder will we be able to
connect Apple Watches to iPads? Anyway, it made sense to extend one of my
existing apps to use the Apple Watch instead of starting from scratch.

Of my iOS apps, I decided that The 19th Hole, my golf scoring app,
would be well suited to the Apple Watch. The problem with using the iPhone
version to score is that you have to keep pulling your iPhone in and out of your
golf bag, sometimes in the rain, sometimes in bright sunlight. Being able to
enter the scores on your wrist sounds like a big improvement. We know that the
Apple Watch is at least somewhat water-resistant, but we are yet to see how well
it performs in bright sunlight, however I would expect that Apple has put
considerable effort into this.

Once I decided to write an Apple Watch app, the first step was to learn how. I
read all Apple’s published documents to get a feel for what was possible and
what user-interface objects would be available. I find online courses very
helpful and by far the best Apple Watch course that I found was Ray
Wenderlich’s WatchKit video tutorial series. The instructors were very clear
and explained how the layout and sizing of objects works on the Apple Watch, as
well as how to set up and move between views and how to communicate from the
Watch back to the iPhone. The layout section of the course was particularly
valuable as no other course I found even mentioned this, although it is crucial
to the interface design and allowing for the two sizes of watch.

I had released an update to The 19th Hole recently in preparation for this.
I wanted to have squashed the bugs and updated the interface, so the only
changes needed would be the WatchKit ones.

The first step in adding a WatchKit app to your existing app is to create a new
target in the Xcode project. Choosing WatchKit actually adds two new targets:
the WatchKit Extension which lives on the iPhone and supplies the code for the
Watch, and the WatchKit App which lives on the Watch and provides the interface.

I decided to use a paged interface with one page per hole. Each of these pages
has a table, with one row per player. A slider with plus & minus buttons lets
you enter the score for each player and the total score for each player is also
displayed.

Apart from this data entry view, I have a splash screen which shows you the
current round as set up on the iPhone and a final summary screen showing
everyone’s totals.

These images are taken from the Apple Watch simulator running in 42mm mode.

The biggest programming problem was getting the communications working beween
the two devices. The 19th Hole uses Core Data for all data storage. My first
attempt shared this data between the two apps, allowing both to read and update
the database. This almost worked, but if both apps were open, then changes in
one device did not get across to the other. It seemed that the data was cached
and I was unable to find a way to force either app to update every time.

My next attempt kept all the data in the iPhone app and had the WatchKit
extension ask for whatever data it needed and send changes to the iPhone app.
This worked much better and I was able to get live updates between the two
devices.

The other issue is the fact that I have never seen, touched or used an Apple
Watch. This means that I had to guess a lot of things:

how well will it perform?

will the icon look OK?

are the controls large enough to use?

will the text be large enough to read?

My main philosophy was to keep the Watch app as simple as possible and use the
standard interface elements, font sizes etc. Hopefully that will work.

The final step was submitting the app to iTunes Connect for review. It was not
clear to me how to do this, so I logged into iTunes Connect, created a new
version and entered the meta-data. I couldn’t see anywhere to say anything about
the Watch. I archived the main iOS app as usual and validated it with the Store.
I had a few things to fix up, but I got the build submitted.

Back to iTunes Connect and once the uploaded build had been processed, I was
able to select it and click “Submit for Review”. At this point, the page
reported an error and showed me a new section where I could upload the Apple
Watch icon and screen shots.

I had been unsure how the icon would look when made round, but it looks OK on
the iTunes Connect page. How it will look on a tiny watch screen remains to be
seen. Anyway, once I had my icon and screen shots uploaded, I was able to
proceed to the next step. But then I got a message saying that the app could not
be processed - no explanation. Thankfully, I had seen some developers on Twitter
reporting this, and somebody said that the solution was to remove the alpha
channel from your screen shots. Sorry for not giving credit here - I forget who
said this, but it worked, so thank you whoever you are.

So now my app is waiting for review and who knows how long that will take.
According to App Review Times, the current estimate is 8 days, but the
trend is heading upwards. I would expect that to blow out in the next few weeks
as developers try to get their apps ready for the Apple Watch release date of
April 24th.

LiveCode stacks

When I converted my site to Jekyll & GitHub, one of the things I left behind was
a collection of LiveCode (Revolution) stacks. For many years I was active in the
Revolution community before going in other directions and over that time, I
built up a small library of stacks that I released into the public domain.

LiveCode is a cross-platform rapid development environment. There is an
open source community edition available for anyone wishing to get started.

I had assumed that since I had not been an active LiveCode user for many years,
these stacks would have become worthless. But in the last couple of days, I have
received a couple of queries from people looking for them.

So I created a new GitHub repository and uploaded them all to here:
LiveCode stacks

None of these stacks have been updated recently, but feel free to use or adapt
as you see fit. They have not been tested using recent versions of LiveCode, so
may not work as expected. As stacks are provided as is. Use at your own risk.

Icon Builder 3.0.1

Version 3.0 got no announcement because it was not the release I wanted.

Having downloaded the Xcode 6.2 & 6.3 betas, I had worked out what icons were
needed to a WatchKit app. This, combined with several other changes, made me
bump the version number to 3.0.

Sadly, Apple rejected the update because it referred to pre-release products. So
I pulled all mentions of WatchKit out of the interface and meta data and got 3.0
released.

After the Apple keynote on March 9th, I re-enabled the WatchKit portions of the
app and re-submitted to the App Store, hoping that with the WatchKit SDK now
part of the official Xcode release, Apple’s reviewers would allow it to get
through this time.

This worked - in fact the app was reviewed and accepted within 6 days - so now
Icon Builder adds WatchKit to its list of supported platforms.

Actually, Apple may have done me a favour in rejecting the first one as they
changed the specifications for the icons slightly between Xcode 6.2 beta and
Xcode 6.2 release.

19th Hole

19th Hole is the golf scoring app for everyone, and it is available from the
iTunes
App Store.

Whether you are playing for the club championship, having a weekend round with
friends or playing pitch’n’putt with the kids, 19th Hole makes it easy to keep
score.

Designed for fast, accurate score keeping with a color scheme chosen for optimal
outdoor viewing, 19th Hole uses a simple setup process and an intuitive,
gesture-based score entry system. During and after the round, you can see totals
and results using various methods: total strokes, total putts, match play (Irish
match play for more than 2 players) & Stableford.

19th Hole now includes an Apple Watch app so strokes can be entered quickly and
easily using the watch to avoid having to pull your iPhone out of your bag.

When you have finished, you can archive the score card for future reference and
email the completed card to your fellow players.

Scoring a round is very simple:

Select a course - the last played course is pre-selected.

Select the players - the last set of players is pre-selected.

Tap ‘Start Round’

Optionally enter the players’ handicaps - the last used handicaps are
pre-selected.

After each hole, enter the strokes played by each person, on your iPhone or
Apple Watch.

You can also record putts and various other statistics (iPhone only).

iPhone

Apple Watch

Courses only need to be entered once and are then saved for future use.
Enter the course name, number of holes and select the tees in use. For each hole,
enter the par, index/handicap, and the distance from each tee.

If you are in a hurry to start the round, enter the name of the course and the
number of holes. The rest of the data can be entered for each hole as you play,
or can be edited later.

Players can be selected from your Contacts or entered manually. Add email
addresses so the completed cards can be emailed after the round. Choose an icon
for each player. If a player was selected from Contacts, you can use the photo
assigned in the Contacts app.

Gesture-controlled:

All scores are entered using a special number button that you tap, then drag
your finger up or down the screen to raise or lower the number.

Hold your finger down on the number, then move it up or down to change the
number displayed. To make it easier to see what you are doing, hold your finger
down on the number, then first drag to one side before dragging up or down. Play
the video below to see how this works.

During a round, cumulative statistics are shown at the bottom of the screen.
For a more complete score card, you can swipe downwards in the middle of the screen.

Tap on the hole details at the top of the screen to edit that data.

After the game:

While relaxing at “The 19th Hole” after the game, you can check the scores and
swipe back and forth between holes to see what happened during the round.

Once you are sure the scores are correct, tap the “Action” button in the top
right. You can add some notes to the round at this point or archive the round so
that the completed score card is saved on your iPhone. After this, you will not
be able to make any further changes.

Completed rounds are listed when you tap “See Old Cards” with the most recent at
the top. Tap one to see the complete score card for that round. Tap “Strokes”,
“Putts” or “Stableford” to change what is shown for each hole. The summary is
shown at the bottom.

App Store Preview Videos

Apple now allows app developers to add a video preview of their app when
uploading to iTunes Connect. This video is shown to potential purchasers when
they are looking at an app in the iTunes App Store, just like the screen shots.

I have been working on an update to 19th Hole and since it uses a custom
method for data input, I decided that a video would be really useful in this
case.

The first step was to work out how to record video from my iPhone. In OS X
Yosemite (10.10), this can be done using QuickTime Player. Connect your device
to your Mac using a Lightning cable (I think it has to be a Lightning cable -
the old cables will not work). Open up QuickTime Player and choose “New Movie
Recording” from the File menu. By default this shows input from the Mac’s
FaceTime camera, but just to the right of the red Record button, there is a down
arrow that shows a popup menu. Click this and you can select your iPhone as the
Camera. Since I wanted the sound effects included, I also selected my iPhone as
the Microphone, but if you want to provide a voice-over or sound-track, you
might want to change this.

That handles the technical side of recording, but I needed a way to show where I
was tapping and pressing on the iPhone screen. After some searching, I found
Touchpose which was exactly what I wanted. Since it requires changing the
main.m file, as well as changes to the app delegate, I created a branch in my
app’s git repository so that I could apply these changes temporarily, but save
them for next time. The only alternation I made to the default settings was to
change the color of the cursor indicator to suit the color scheme of my app. And
since this was a temporary change, I set it to show the cursor indicator all the
time, not just when the screen was mirrored. All the details are shown in the
sample project.

Next step was to actually record a session. After my first attempt (which lasted
about 67 seconds), I checked the Apple specs and found that the video could not
be longer than 30 seconds. So I re-thought what I wanted to include and tried
again. It took a few tries to get what I wanted, but finally I ended up with a
.mov file that was 26 seconds long.

On to iTunes Connect where I had the new version of the app set up already with
its screen shots. Since I have an iPhone 6, the video was only suited for the
4.7 inch section. So I dragged it into the drop zone and waited. No good - the
video frame rate was too high. It has to be 30 fps or less. QuickTime Player had
made a video that was 50 fps.

The app I usually turn to for any video conversion needs is Handbrake. So I
ran the app through Handbrake, specifying a frame rate of 30. This converted the
video to .mp4 instead of .mov, but it was 30 fps. It wasn’t until I tried to
upload it to iTunes Connect that I realised Handbrake had cropped the video from
750 x 1334 to 750 x 1330. After searching through the settings, I found where I
needed to turn on custom clipping and set it to 0 so that the original
dimensions were preserved. But iTunes Connect still didn’t like it, although
this time the error message was un-informative.

Eventually, the brains trust on the other side of the room suggested iMovie. Not
only that, but he found that once the original had been dragged into iMovie, the
share options included an “App Preview” setting. This gave us a .mov file of the
correct dimensions and the correct frame rate which iTunes Connect accepted.

iTunes Connect that allowed me to select the poster frame for the video and save
the changes to the app meta data. At that point, it showed a notice saying that
the app preview was being processed which could take up to 24 hours. It appears
that the processing has been finished, as that notice has disappeared.

For the next stage, I ned to wait until the app gets reviewed and hopefully
approved. Then it will be interesting to see how the video looks in the iTunes
App Store.

As a reward for reading this post, here is a pre-release of the video, showing
how to enter the score data for a hole of golf using 19th Hole:

Testing automation

Firstly, there is the structure of the post Markdown document, which really
boils down to the file name and the header.

I have set up a macro in Typinator so that I just type the title of the
post in a text document. I copy that title to the clipboard and type the
shortcut. The header is then created with the title and the formatted permalink.

To save the document, I use another Typinator snippet to convert the title
(still in the clipboard) to lower case and to replace the spaces in the title
with dashes.

For starting the local Jekyll server, I have turned to an Alfred workflow.
I have two actions in the workflow. One opens Terminal, cd’s to my site folder
and runs the command to start the local Jekyll server. The second opens my
default browser to the local Jekyll test address.

Both these actions happen simultaneously so the browser usually fails until
refreshed. The server is left running in Terminal so I can shut it down when
finished testing.

After writing the post, the final stage is to publish, so I need to work out the
commands for doing a git commit and push. Then I should be able to automate
those tasks.

Testing the git commands using Terminal, I have come up with the following
sequence:

git add .
git commit -a -m "Commit message here"
git push

The commit message could be the title of the post, so I need a way to construct
the command and then execute it. Typinator is good at text manipulation, so I
constructed another macro that takes the clipboard, uses it as the commit
message and performs the git commands. This gave a good commit message, but the
actual commit failed, so that was no use.

So then I went back to Alfred and created a workflow there with a series of
Terminal commands to perform the actions above. This only allows a generic
commit message, but it works as expected.

So there is still room for improvement, but with a set of macros, I can automate
a lot of the standard text entry, which is always good for reducing errors.

The sequence now is:

Open the text editor and type the title of the post.

Cut this into the clipboard.

Run the Typinator macro to fill in the post header.

Save the post file, using the Typinator macro to construct the file name.

New Site for TrozWare

Welcome to TrozWare’s new site.

It appears that I am not alone in deciding to move away from WordPress.
WordPress is great - easy to set up and with lots of cool themes to allow
customisation of your site. But it is slow, especially if (like me) you are
running on a low-cost shared server.

I had been reading about Jekyll, so I decide to give it a go and also host
my site on GitHub, taking advantage of their faster servers.

I followed the advice given by Girlie Mac and performed the migration from
my self-hosted WordPress site. I am using the Pixyll theme by John
Otander with a few tweaks of my own. The site is much faster to load, and I
am hoping that the easier editing will inspire me to write more posts.

Of course it wasn’t all positive. WordPress did give me some features I liked,
but I think overall the result is better.

WordPress

WordPress gave me a full LAMP stack, so I could run my own PHP scripts.

WordPress gave me a search function.

Commenting was built-in.

Jekyll

Jekyll builds the pages out as static HTML, so all pages are pre-generated for
fast loading.

Writing for Jekyll is pure Markdown so it is easier to write and preview
locally.

Some of the things I needed a plugin for in WordPress can be done natively in
Jekyll: - tables - syntax-highlighting

For comments, I have switched to Disqus, but I am not sure about it yet. I
will evaluate over the next few weeks. In WordPress, I used a plugin to handle
the spam that inevitably arrived. I am hoping that Disqus will protect me from
that, but I have to see how good a job it does and whether the few real comments
are worth it. A better option might be to turn off comments completely and just
have a contact form (which I have added using Formspree). Working in
Markdown is great. I love how I can have a really clean look in my editor and
still end up with well formatted HTML. I use Coda 2 on my Mac as my standard web
editor, so that is what I am writing in now. I will probably experiment with
other Markdown editors as I go. And for any Mac users out there working in
Markdown, I highly recommend Brett Terpstra’s Markdown Service Tools.

World Time In Words

World
Time In Words version 3.0 is now available in the Mac App Store.

With version 3.0 of this app, I have changed the name to “World Time In Words”.
This is to reflect what I feel to be the most useful feature of this app: the
ability to convert between time zones.

It has two other new features:

The time shown in the menu bar can now be set to use 24-hour time. Go to
Preferences to change this.

If you temporarily need to see the time in digital format, hold down Option
when opening the menu.

And there is one other thing in this version that I am almost too embarrassed to
mention: after using this app for about two years, it was finally pointed out to
me that the 3rd of every month was being shown as the “3th”. Oh dear - it was a
copy-paste error but I should I found it a long time ago.

As always, please let me know if you have any suggestions for future versions.

Email clients for Mac and iOS

Some people are moving away from email, but for me, it remains the best way to
communicate online. I get to keep a record of conversations and the attached
files are with the text so I can always see the context.

But I think everyone would agree that Apple have dropped the ball with Mail in
OS X Mavericks, and to a lesser extent, in iOS 7.

So I have been on a campaign lately to find an email client that suits my needs.
I don’t feel that I have found the perfect answer yet, but I am getting there.

The first step was to work out what I really needed in an email client:

support for IMAP accounts and Gmail accounts

unified inbox - all accounts shown
together

conversation threading

support for POP accounts (optional)

On the Mac, I have narrowed it down to two clients that I am swapping between
every few days: Unibox
and Airmail.

Unibox is different in the way it displays your emails. It is much more focussed
on people and conversations, so the side bar shows all the people who you have
sent emails to or received emails from, grouped by date. I really like the
merging of incoming & outgoing emails, but it can be a bit weird if you delete
the latest email from someone who then disappears from sight.

Emails are grouped by a single person, not by conversation. There is a button on
appropriate emails to toggle conversation view for that particular thread, but
it doesn’t stick.

In order to show a conversation, they truncate emails in the main part of the
window and show a “More” button at the bottom of the email to expand it. This
was annoying, but in the latest beta, it performs much better, so you are not
continually tapping this to see a long email.

Airmail has a more conventional display. Threading and the layout of threaded
emails are both very nice. There are multiple view options, which I find can get
a bit messy looking, so I prefer the “Minimized View” setting. Airmail also does
POP accounts which is a plus.

The main reason I keep going back to Unibox is the unification. I have grown to
like having sent and received messages all in the same window without having to
go and find them somewhere else.

On the iPad, I am currently using
Boxer and have tried
numerous others. Molto
was quite good and the interface was fun, but it would only use landscape mode
and like to be able to swap. Boxer is not great in portrait mode, but it does
work.

So the jury is still out for iPad email clients, but on the Mac, I am leaning
towards Unibox.

Berio Sequenza VII

So my latest app is way outside my usual sphere but that’s what happens when
family decide that what you do might actually be useful!

My son is an oboist and he is currently learning Berio’s Sequenza VII for Oboe.
This is a weird piece without a standard time signature. Instead each line has
13 bars with each bar being allocated a certain time span in actual seconds. As
can easily be imagined, this makes learning and practicing this piece more of a
mathematical exercise than a musical one.

So I wrote him an app to sound out the end of each bar. Once he and his teacher
used it, a few more features crept in and now I think it will be of great
assistance to any student or teacher trying to work on this piece.

While I doubt that many oboists frequent this web site, it anyone who does can
pass this on to any oboist, I would be very grateful, and I think the oboist
would be too!

The app is available through the
iTunes
App Store.
More details are on this page.

Berio's Sequenza VII

Luciano
Berio wrote a series of Sequenzas for various instruments with Sequenza VII
being the one for oboe.

Preparing this work creates some unique problems for the oboist as Berio did not
adhere to any time signature that could be indicated by a metronome. Instead,
each line consists of
13
bars (measures) with each bar’s length specified in exact seconds.

When my son (an oboist currently studying in Melbourne, Australia) started
trying to learn this piece, it occurred to him that having an iOS app developer
in the family could be of some assistance. So with instructions from him and
with suggestions from other oboists, I have developed the
Berio
Sequenza VII app for iPhone or iPod Touch.

With the default settings it will count the bar lengths, using metronome-like
sounds to mark the starts of bars and lines. The player who needs to practice a
specific bar can easily set the app to start at that bar and even to repeat that
bar length continuously.

Tapping the “i” button at the bottom right of the screen takes you to the more
advanced options.

The “Settings” section deals primarily with the B4 drone that is supposed to
accompany the performance of this piece. While in an actual performance, the
dynamics of this drone would vary, for this practice app it remains at a
constant volume as specified by you. The volume can be set to a percentage of
the iPhone’s current volume setting. If it is still too quiet, plug your iPhone
into a speaker or use some sort of physical amplification. If you prefer to play
with an A other than 440 Hz, that can be adjusted. And finally, the wave form
used to generate this drone sound can be switched between a sine wave or a
triangle wave. Disclaimer: excessive use of this drone may cause loss of
friends!

The Settings page also includes an option to slow down the times for practice.
At 100% speed, bar 1 on each line will last for 3 seconds. The speed can be
reduced to allow each bar to last longer, for use during the learning process.

The “Bars & Sounds” section allows you to customise the various options marking
the start of each new bar. You can specify the number of seconds & the sound
used to count you in after tapping the Start button. You can also select which
of the metronome sounds to use to mark the start of each bar, making the first
bar of each line use a different sound if you prefer. Finally, in case you are
playing so loudly that you are unable to hear the iPhone, you can set the screen
to flash a different color at the start of each new bar.

Jacqueline Leclair wrote a
supplementary
edition of this work in 2000 using traditional time signatures in a way that
almost exactly duplicates the original timings. This app is designed for use
with the original score using Berio’s real time bar lengths.

Icon Builder & iOS 7

Icon Builder 1.2 was released on 18 September 2013.
It was an update with 2 new functions:

The ability to create images to suit an Xcode 5 assets library

The ability to create icons with the required sizes for IOS 7 apps.

Knowing that iOS 7 apps can only be built using Xcode 5, I linked the switch for
these 2 abilities in a single check box.
The problem was not really that they were in a single checkbox but that I had labelled
it badly, so it was not obvious that this was what needed to be checked to create
iOS 7 sized icon files.

After some feedback from early users, it became clear to me that this was not
enough. So 1.2.1 is now waiting for Apple’s approval.
The changes in this version are:

More informative labelling of the checkbox.

The checkbox is checked by default is Xcode 5 is installed

While waiting for the new version to be approved, please be aware that iOS 7
icon sizes will only be generated if you select “Check Assets (for Xcode 5.x or
later)”

Icon apps updated

Icns
Maker and
Icon
Builder have both just been updated to support Xcode 5.

Icon Builder is a Mac app that takes your images and creates all the required
icon files for use in your iOS apps.
It now supports Xcode 5’s image assets folders and if you are using Xcode 5, it will
create the icon sizes required for iOS 7 app.

Icns Maker is a Mac app that takes your images and creates icons for use in your
Mac apps.
For Xcode 4 or earlier, it creates a .icns file.
For Xcode 5, it creates a folder of images for use in your project’s image
assets folder.

Markdown

For some time now, I have been aware of the increasing trend towards using
Markdown for text editing and for creating HTML. Markdown has been on my list of
“things I should learn some day” so I was interested last week to read about a
new iBooks book called The MacSparky Markdown Field Guide. This was
sufficient inspiration so I got the book and read through it this weekend.

Actually, to say that I read through the book is a mis-representation. The
book was written using iBooks Author specially for the iPad and contains screen
casts and interviews as well as text. But by the end of it, I now feel I have a
basic understanding on Markdown and the ways in which I can use it.

I guess the really big thing about using Markdown is that is creates plain text
files that are human-readable even without being converted to HTML. This makes
them future-proof since they are not tied to a proprietary file format that may
cease to exist at any time.

Using Markdown:

Since this web site is a self-hosted WordPress site, my next step was to look
for a WordPress plugin that would allow me to use Markdown to create my posts. I
could have used a Markdown editor that had HTML export, but I wanted to try
something that would eliminate the extra step. The first one I decide to try was
Markdown on Save Improved.

One of the main reasons for choosing this one was that it stores the posts as
both Markdown and as HTML. This saves time when going back to edit a post,
avoids the constant changes that creep in when converting between formats all
the time, and makes it so that the post will still display correctly even if
Markdown is no longer supported. The only problem I have found so far is that it
doesn’t automatically create links & image links using the Markdown format, but
uses standard <a> and <img> links instead.

My next stop, since I always use a Mac, was to get Brett Terpstra’s collection
of Services for Markdown. These add a lot on convenient shortcuts: one of
my favourites is the ability to convert inline links to references links for
increased readability while editing.

First Impressions:

So having written this first post in Markdown, how do I feel about it? I haven’t
really tried anything too weird this time, but there are a few things that were
very easy to do. Particularly in the paragraph where I was talking about links &
images and wanted to include the tags as text without having it interpreted as
HTML. All I had to do was surround the text with back-ticks.

Links are vastly easier to manage and edit in Markdown. I miss the ability to
specify that links should open in a new tab - I prefer to have that setting for
links that take you outside my web site, but the modern theories on usability
seem to be heading towards deprecation of this feature, so I may just stop using
it.

With the standard WordPress editor, I always felt that I was fighting it. I had
to swap between the visual & HTML editor tabs and when I swapped tabs, things
would sometimes change without me doing anything. So far, I feel more in control
using Markdown and although I have lost the WYSIWYG visual editor, I no longer
have to wade through the HTML editor to get the effect I want or to remove the
results of a few careless clicks.

What next?

Some of the things on my wish list would be solved by a better editor and some
by more powerful syntax.

Editor:

Adding links & images using Markdown style instead of HTML

Being able to create lists

Markdown makes this very easy but this WP plugin does not support lists as
far as I can tell

So these lists are in HTML

Syntax:

Alignment of text & images

Using a stand-alone Markdown editor would solve the editor questions, but I
wanted to try writing this post completely in WordPress.
And with the alignment, there is nothing to stop me adding CSS to the Markdown.

Next time, I will test out a different WordPress Markdown editor and see how
that goes. I will also test using a standalone editor and exporting its HTML to
create a post.

A Knight's Move 1.3

UPDATE: September 2016 - A Knight’s Move for iOS is no longer available.
A Knight’s Move for Mac is still supported.

A Knight’s Move has been updated to version 1.3. The Mac version is available
through the
Mac
App Store.

Three new level packs:

Eight by Eight

Bishops Rule

Castles

Eight by Eight has every puzzle set in a chessboard sized grid with more
conventional placing of pieces.
Bishops Rule has at least one Bishop in every puzzle.
Castles has a Castle or Rook in every puzzle and is suited to players who would
like more of a challenge.

New feature:

When your knight has been taken, you have the option to undo the last move so
you can try again without losing the moves you have already made.

Man Reader (no SB)

These instructions are no longer valid. As of version 1.5, the App Store version
of Man Reader has solved the sand-boxing issues and is now as powerful as the
non-sand-boxed version.

The non-sand-boxed version will no longer be supported or updated, so please
revert to the App Store version.

If you find that Man Reader is not working well for you due to Apple’s
sandboxing restrictions, then you can download a non-sandboxed version here. To
find out more about this, including how to test if you are affected, read the
Sand-Boxing Man Reader page.

The non-sandboxed version will only work if you have the App Store version of
Man Reader already installed.

When you run ‘Man Reader (no SB)’ for the first time, it will check to see if
you have a valid installation of ‘Man Reader’ that you have purchased from the
App Store.
If you do not, ‘Man Reader (no SB)’ will offer to take you to the App Store and then
quit.

If you already own the App Store version of Man Reader and ‘Man Reader (no SB)’
has started once, you can delete the App Store version and ‘Man Reader (no SB)’
will keep working.

To install ‘Man Reader (no SB)', click the download link below. This will
download ‘ManReader-noSB.zip’. Double-click on this file to un-zip it, and then
move the ‘Man Reader (no SB).app’ into your Applications folder and use as
normal. Do not delete the App Store version of Man Reader until ‘Man Reader (no
SB)’ has been run at least once.

I found out today (thanks Ron) that under OS X 10.10.3 the security settings no
longer allow the downloaded version of Man Reader (no SB) to run, despite the
fact that I have signed it with my Apple Developer ID. OS X gives a very
un-helpful dialog reporting that the app is damaged. In fact the app is fine,
but being blocked by the security settings. The solution as shown at
TechRecipes is to change your security system preferences to allow
downloaded apps from anywhere. You only need to do this temporarily as after you
have run the app once you can set this setting back to whatever you had before.

Sand-Boxing Man Reader

These instructions are no longer valid. As of version 1.5, the App Store version
of Man Reader has solved the sand-boxing issues and is now as powerful as the
non-sand-boxed version.

The non-sand-boxed version will no longer be supported or updated, so please
revert to the App Store version.

As with all apps in the App Store, Man Reader is restricted by Apple’s
sand-boxing policy. Sand-boxing is a great thing. It isolates apps from each
other and from the system, making it far less likely that a problem app will
cause wide-spread havoc. However for an app like Man Reader, this can lead to a
drop in functionality.

Due to the permissions limitations of sand-boxing, Man Reader can only search
defined paths on your system drive e.g. /usr/, /opt/
This is where the default man pages are all stored, but if you install other software
(Xcode is a good example), then Man Reader may not be able to list all the available
man pages on your system.

To tell if Man Reader is missing man pages, copy & paste the following command
into the Terminal app:

whatis . >> ~/Desktop/whatis.txt

Man Reader runs this command internally when it starts, but the Terminal app is
not sand-boxed and so can access everything.
Running this command will create a text file on your desktop with a list of all available
man pages on your system. Open it in a text editor that can show the number of lines
in a file. TextWrangler from Bare Bones Software is a good free editor that
will do this.

To check what man pages ManReader can read, go to Finder and select ‘Go to
Folder…” from the Go menu. Paste in the following path:

You will see two files: open the one called ‘ManReader.raw’ in your text editor.
This is the result of Man Reader running the whatis command. Compare the number
of lines in the two files. Don’t worry about the order of the items in the file
as that may vary, you are only concerned with the total number of lines in each.

There may be one or two lines more in the whatis.txt file but if there is a big
difference, then you are being sand-boxed…
As an example, on my system, the whatis.txt file contains 8954 lines and the ManReader.raw
file contains 2320 lines!

If you are affected by this or think that you might be, I now have a
solution - actually two possible solutions:

If you have already bought Man Reader from the App Store, then you can
download a non-sandboxed version. This will only work if you have the App
Store version of the app installed.

If you do not already own a copy of Man Reader, and want to buy it
un-sandboxed, then you can now buy it directly.

Icon Makers & Retina Macs

Icns Maker which makes an icns icon file for Mac apps, and Icon Builder which
makes the suite of png files needed for iOS apps, are both compatible with the
Retina MacBook Pro.

However it was recently brought to my attention (thanks Cameron), that when
running on a Retina MBP, all the icon files were exactly twice as large as they
should be. The Icon.png file which supplies the main app icon for iPhone apps
should be 57 pixels by 57 pixels. Using Icon Builder on a Retina MBP produced an
Icon.png file that was 114 x 114 pixels.

I have now worked out how to persuade the Retina Mac that when I ask for an
image size, I actually want that size, not the size that OS X thinks would look
better. Updates to these 2 apps will be submitted to the App Store for approval
later today which will solve the problem.

In the meantime, there is a work-around for Retina MBP users: force the app to
run in low resolution mode.

In Finder, open your Applications folder and select the app (this works for both
Icns Maker and Icon Builder). Press Command-I or choose Get Info from the File
menu which will open a window like this:

Check the checkbox labelled “Open in Low Resolution”. Next time the app is
opened, it will ignore the Retina options and use standard resolution only. This
will create icon files with the correct sizes. However text may look slightly
fuzzy.

When the updates to these apps become available, make sure you go back and
un-check this setting to return to Retina mode.

A Knight's Move updates

UPDATE: September 2016 - A Knight’s Move for iOS is no longer available.
A Knight’s Move for Mac is still supported.

A Knight’s Move for iOS has been updated to take advantage of the taller iPhone
5 screen.

In-app purchasing of packs has been removed from both Mac & iOS versions.
For iOS, the app is now free but supported by iAds (please click through if you would
like to show your support).
Apple does not have an ad system for Mac, so the Mac version is now a paid app
that includes all the puzzle packs.

The in-app purchasing was an interesting experiment, but the ratio of purchases
to downloads was too low to sustain the development.

App Store Review Times

There are been a lots of stories going around about lengthening Mac App Store
review times.
Shiny
Developments crowd-sourced data certainly backs this up although they have
much more data for iOS apps than for Mac apps.

Some people, including
Lex
Friedman of MacWorld and
John
Gruber of Daring Fireball, are suggesting that the delays are due to the
rush of new apps to support the iPhone 5 and iOS 6. This implies that there is
only one set of review staff and that a large proportion of them have been moved
from Mac to iOS apps.

I think this is an incorrect analysis. The slowdown started before iOS 6 and
before the iPhone 5. I think it started in June when Apple started to enforce
Mac sandboxing.

As discussed in a previous post, I have had a lot of trouble getting Man
Reader to be sandbox-compatible leading to many rejections. One problem was that
I had implemented sand-boxing before the deadline, but with some temporary
entitlements to allow read-only access to required system files. This
entitlement was approved initially, but after one rejection, an Apple reviewer
told me that they had been approving all requested entitlements before the
deadline, but now were actually reviewing them all.

To me, this seems like a rather silly thing to have done which has now returned
to haunt them. Instead of allowing developers time to get used to the
restrictions, Apple reviewers allowed developers to think that their apps were
sandbox-complient already. Then Apple was faced with the enormous task of
re-checking all the entitlements that they had previously allowed without
checking. This was unfair to developers and has only created extra work for the
reviewers.

Here is a table showing the recent review times for my Mac apps:

App

Process

Review days

Dates

Time In Words

update

22

Sept 22 - Oct 14

Icns Maker

new app

24

Aug 5 - Aug 29

A Knight’s Move

update

26

Sept 6 - Oct 2

Icon Builder

new app

33

Aug 22 - Sept 24

By comparison, when I submitted an update to A Knight’s Move for iOS in October,
it was passed in only 8 days.

Icon makers for Mac & iOS apps

Announcing two new apps for creating icons for with Mac or iOS projects:

Icns Maker helps you convert a single image into a .icns file in two
steps.Icon Builder creates all the files needed to set up your icons for any iOS project.

Creating icon files for Mac apps:

In versions of Xcode before 4.4, Apple provided an app called “Icon Composer”.
It allowed you to drag images into a window and export a .icns file for use in
your Mac apps. With Xcode 4.4, Apple has changed the way icons are handled for
Mac apps and “Icon Composer” is no longer supplied.

The Xcode docs describe the process you need to go through to make a .icns file:
create a suite of image files of the correct size and with the correct file
names, bundle them into a specially named folder and then use Terminal to stitch
them together.

Drag in an image file (preferably 1024x1024 but 512x512 will also work).

Click a button.

There are more options available for fine-tuning your icons allowing you to
select different images for the various sizes, but this is all that is needed
for basic operation.

Icns Maker is available from the
Mac
App Store.

Creating icon files for iOS apps:

Icons for iOS apps are not bundled into a single file like a Mac .icns file. You
add various .png images to your project. Depending on the devices supported by
your app, you will need many different sizes of icon file. There are some icons
for iPad only, some for iPhone / iPod Touch only and others required for any
device. Additionally, you will need larger versions of each image to support
Retina displays.

Icon Builder is a Mac app that does all this for you. As with Icns Maker,
you just drag your image into the app and click a button. You can also select
which devices your icon needs to suit and use different images for the different
sizes if you want finer control.

When the app creates your icon files, it generates a ReadMe file with the
information needed for installing these files in your project, including
information to copy & paste directly into your Info.plist file.

Icon Builder is available from the
Mac
App Store.
Note that although this app builds icon files for iOS app, it runs on a Mac.

Naming

Originally these apps were named in a consistent manner: Mac Icon Builder and
iOS Icon Builder. However both these names were rejected by Apple - you are not
allowed to use the words “Mac” or “iOS” in any app name sold through the Mac App
Store.

Then I tried Icns Maker and Icon Maker. Icns Maker was approved, but there is
already an app called Icon Maker, so I went with Icon Builder. But by that time
Icns Maker had already been released, so there was no way to make the names more
consistent.

Icon Builder will create an AppIcon set inside the “Assets.xcassets” folder for
that project.
The icons are immediately ready for use in your project with no installation necessary.

Why is this necessary?

Depending on the devices supported by your app, you will need many different sizes of icon file. There are some icons for iPad only, some for iPhone / iPod Touch only and others required for any iOS device. Mac apps use completely different icon sizes. Apple Watch apps need a completely different set of icons and now with iOS 10, Messages apps and Sticker apps require even more - 2 different icon sets for Messages app. Additionally, you will need larger versions of each image to support Retina displays.

These icons must be in PNG format, with the color space set to sRGB (or P3 for iOS apps, but Icon Builder always uses sRGB) and for iOS apps, with no transparency and with alpha channel in the image files.

Your Xcode project contains a special folder called “Assets.xcassets” which contains all the image files used in your project, including the app icons. Icon Builder will install the icon files into your “Assets.xcassets” folder automatically and the icons are immediately ready for use in your project with no installation necessary.

Icon Builder still allows you to create the old-style .icns file if required by selecting “Mac icns” in the device family popup menu. This can be useful for other development environments or when making icons for documents in your Mac app.

You will get the best results if you start with a 1024 x 1024 image.

Using the icon images:

Icon Builder creates all the required image files in a folder called “AppIcon.appiconset”, “AppIcon-Watch.appiconset” or “iMessage App Icon.stickersiconset” inside the “Assets.xcassets” folder for your project. If you already have images stored in an appiconset folder, Icon Builder will not over-write them, but will add a new folder e.g. “AppIcon-1.appiconset”. You can then switch between AppIcon sets in the project settings for your target app.

If you prefer to add the icon files manually, select a folder that does not contain a .xcodeproj file and the icon sets will be saved directly to that folder. You can then drag the iconset folder manually into “Assets.xcassets” in your Xcode project.

What’s New in version 5?

Icon images have the correct sRGB color profile attached.

For iOS icons, transparency is replaced by white and the alpha channel is removed from the image file.

The icons created match the latest Apple guidelines.

The app has been completely re-written in Swift to use the latest macOS APIs so only supports macOS 10.13.x or later.

FAQ

I thought there were only 2 steps before - why are there 3 now?

The 2 step process gave you a folder of image files. You then had to install them manually. So really, there were always three steps, but the app was not helping you with step 3. By adding a third step asking you to locate your project folder, I was able to make the app install the icons for you automatically. So the app is doing step 3 for you.

What if I want to install the icon files myself?

When asked to select a folder to save the icons, select a folder that does not contain a .xcodeproj file. Icon Builder will save all the files, but not install them into an Assets.xcassets or Images.xcassets folder automatically.

Yes. Mac apps use image assets just like iOS apps, but with different image sizes. Select “Mac App” in the Device popup to create icons for a Mac app.

Icon Builder still allows you to create the old-style .icns file if required by selecting “Mac icns file” in the Device popup menu. This can be useful for other development environments or when making icons for documents in your Mac app.

What is the difference between Mac App Icon and Mac icns file?

“Mac AppIcon” will create the modern AppIcon set of images for inclusion in your Assets.xcassets.

“Mac icns file” will create an old style .icns file with all the image sizes embedded into a single file. Open the file in Preview to see the contents.

Does Icon Builder create icons for use in Watch Kit apps?

Yes. Select “Apple Watch” from the Device popup. Create a WatchKit target in your iOS project if necessary. When you are choosing the location to save the icons, select the folder containing the main .xcodeproj file. Icon Builder will find the WatchKit App folder and save the icons to the WatchKit App's Assets.xcassets folder. The icon set will be called AppIcon-Watch to help you distinguish between sets when allocating them to your apps.

When the WatchKit icons have been made, Icon Builder will ask you if you want to use the same image to create the icons for the parent iOS app. Unless you want a different icon for the parent app, select the parent app device at this point to create the second set.

Does Icon Builder create icons for use in iMessage apps and Sticker Pack apps?

Yes. Select “Sticker Pack App” or “iMessage App” from the Device popup. When you are choosing the location to save the icons, select the folder containing the main .xcodeproj file and Icon Builder will create the icon sets accordingly.

iMessage apps require two sets: one for the Messages extension and one for the parent iOS app. When the iMessage icons have been made, Icon Builder will ask you if you want to use the same image to create the icons for the parent iOS app. Unless you want a different icon for the parent app, select the parent app device at this point to create the second set.

For Mac, iOS and Apple Watch apps, all the icons are square. For Sticker Pack apps and iMessage apps, most (but not all) of the icons are letterbox-shaped. Icon Builder displays your starting image in letterbox format when you choose “Sticker Pack App” “iMessage App” so that you can see how it will look.

Apple requires that iOS icons have no transparency so Icon Builder displays the image like that so you can confirm the look. If you do not like the default change, edit the image to remove the transparency before using Icon Builder.

What versions of macOS and Xcode do I need?

This app requires macOS 10.13 as it uses the latest APIs to manipulate images.

Xcode 9 is the latest version, but Xcode 8 will probably work.

I don’t use Xcode, I use an alternative IDE. Can I still use the icons created by this app?

Yes, you can save the icon set to a folder and install the icons manually in the IDE of your choice. If your IDE requires a .icns file, select “Mac icns file” from the device popup.

What if my starting image is the wrong size?

If your image is not the correct size, it will be cropped or expanded when you drag it in.

It will then be resized to create all the required image sizes.

If this does not give the result you want, resize or crop the image before dropping it into Icon Builder.

How do I start again with a blank slate?

Choose “New” from the File menu, or press Command-N.

Do I have to drag images into the app?

No, you can copy & paste an image file, or an image.

Or choose “Open Image…” from the File menu, or press Command-O.

How can I delete the icons from my project?

Select “Assets.xcassets” in the project navigator.

In the next sidebar, you will see a list of the asset sets in your project.

Select the one you want to delete (e.g. AppIcon, AppIcon-1, AppIcon-Watch) and press the Delete key.

I have an old project with no “Assets.xcassets” - how do I add that?

Select the project at the top of the Project Navigator.

Make sure you are editing the target and go to the General tab.

In the “App Icons” section, click the “Use Asset Catalog” button.

The “Assets.xcassets” folder will be created and any existing icons will be migrated to the new structure.

What if I want to use the images from a Mac .icns file?

Drag it in just like any image file. However the largest image in an .icns bundle is 512 x 512, so you may want to create a larger version.

Why are there files with @2x and @3x in the names?

These are for high-resolution displays. iOS knows it needs a certain image size, but if the device has a Retina display, the system will look for an @2x file so it can squeeze twice as many pixels in and make it look sharp. For the larger or more recent iPhones, the system will use the @3x files if they are available.

Updating apps for iPhone 5

I have started work updating my iOS apps to fill the larger screen of an iPhone

My iPhone 5 is on order - I missed out on the first shipment, but hopefully
it won’t be too long. Meanwhile, I will just test in the iPhone Simulator and
hope this is OK.

But it was a puzzle to me how to get an app to fill the longer screen. I have
the latest Xcode and the latest Simulator which allows you to specify what
screen size iPhone to simulate. So I re-built an app and nothing changed - it
showing black strips top & bottom and left my app at the old size.

After trying many different things and reading a lot of the new sections of the
Apple developer documentation, I finally found the answer online:

Apparently the system uses the presence or absence of this file this to detect
whether your app supports the longer iPhone.

I read that Xcode is supposed to warn you of the consequences if this file is
missing, but in my case, when I opened my project, Xcode helpfully used the old
launch image in its place. It showed a warning icon that the image was the wrong
size, but nothing else.

The next problem was how to create this file. I use screen shots, but until the
app worked in the correct format, I wasn’t going to be able to get the screen
shot. So I made it a 2 step process: first I duplicated the original launch
image, renamed it and resized it. It looked wrong but this was irrelevant - it
was enough to get the app working in the correct format. Once I had the app
working, I was able to take a screen shot and create the final launch image.

Once you have the app working in 2 sizes, you have to do more work with the
layout, either using springs & struts or using the modern auto-layout feature. I
find auto-layout confusing, but it is obviously more powerful and the way of the
future, so I am trying to work it out. I found a good tutorial at
Ray
Wenderlich’s site. While directed at iOS 6, it also applies to Mac apps.

A Knight's Move for iOS 1.1

UPDATE: September 2016 - A Knight’s Move for iOS is no longer available.
A Knight’s Move for Mac is still supported.

A Knight’s Move for iPad & iPhone has just been updated to version 1.1

There were some minor changes:

New puzzle pack: Majestic.

iPhone now shows an info button of there is more help available for a
particular puzzle. (This info was already visible in the iPad version.)

Minor cosmetic fixes.

The big change was that all puzzles packs are now included in the free app,
which is now supported by iAds. The sale of puzzle packs via in-app purchasing
was disappointing, so I have decided to try using iAds instead. Hopefully they
will not feel too intrusive, but if you want to support my apps, please tap on a
few of the ads.

Note that iAds will not appear in all countries. You may just see a banner
linking you to my other apps on the iPad. On iPhone, you will not see anything
different.

Man Reader 1.1 Released

The update of Man Reader to version 1.1 has just become available through
the Mac App Store. This update has a bunch of new features - thanks to
everyone who made suggestions.

As detailed in a previous post, there have been major issues getting this
app approved with Apple’s new sand-boxing restrictions fully in place. But to
their credit, the Apple reviewers have been unfailing helpful and polite in
answering my questions and keeping me informed.

Sandboxing and the Mac App Store

As of June 2012, all apps submitted to the Mac App Store have to be sandboxed
i.e. they have to be able to run in a limited environment where they cannot
interfere with other apps or other parts of the system. While this is generally
a good thing, there are problems when apps have legitimate reasons for requiring
access to other resources.

One annoyance for developers is that Apple’s apps are mostly not sandboxed. To
check what apps you have installed that are sandboxed, open up Activity Monitor
(in Applications/Utilities). In the View menu, check that Sandbox is checked in
the Columns submenu. Then you can sort by clicking on the Sandbox title and work
out which apps are already sandboxed. Mail, Preview and Text Edit are now
sandboxed and so is the new Reminders app, but as far as I can tell, no other
Apple apps are. This causes two problems: firstly it is not fair to other
developers if Apple is enforcing a standard which only they are allowed to
break. Secondly, if Apple developers had to follow the same rules as everyone
else, then maybe the system would evolve to become more usable for everyone.

In the Apple developer documentation about sandboxing, there is a section headed
“Determine Whether Your App Is Suitable for Sandboxing”. Here they list numerous
reasons why any app might not work in the sandbox. But the Mac App Store now
makes sandboxing compulsory, so what to do with apps that are not suitable?

Some resources can be requested when building the app: access to various folders
(Pictures, Music, Downloads etc), access to Address Book and Calendar data,
printing facilities, networking etc. Beyond the specified list of entitlements
that can be requested, developers can also apply for “temporary entitlements”
which, if granted, will unlock access to other parts of the operating system.
However these are subject to the whims of app reviewers and will be re-assessed
with every update. Apple has also made it clear that they are intended as a
transition feature and will not be available for ever.

This has lead to a recent spate of popular apps leaving the App Store.
Marco
Arment has discussed this problem with an emphasis on the issue of lack of
confidence in buying from the App Store. If you cannot be sure that an app you
buy will remain in the App Store, then you are less likely to buy it there.

I have run into direct issues with sandboxing already. With
Pic-a-POD, I used to have
links to the Desktop and Screen Saver panes in System Preferences. These used
AppleScripts which required a temporary entitlement to send an AppleEvent. The
app was rejected because of this, so I had to modify this feature - it now just
takes you to the relevant section of System Prefs, but not directly to either
Desktop or Screen Saver. However Pic-a-POD’s help, which runs in Apple’s Help
Viewer app, contains exactly the same AppleScripts and so is allowed to access
these preference panes directly. Try working out the logic of that one!

I have more serious problems with
Man Reader. Man
Reader displays a list of the man pages on your system. Depending on the tools
you have installed, these pages may be in a variety of locations. The shell
command that detects them first reads a config file and then checks the folders
listed in that config file. All it needs is read-only access. With the first
sandboxed version, I asked for a temporary entitlement to give me read-only
access to the startup disk. This was granted, but I have since been informed
that all requested entitlements were granted before the App Store cut-off date.
This may have been meant to be helpful, but it was not useful to allow access
that would later be removed without any warning.

The current version of Man Reader waiting for approval asks for read-only access
to the config file directly and then to every folder listed in that config file.
If approved, this should be able to access all the man pages on a system. I have
no idea whether these entitlements will be granted, but if not, then I will have
to remove Man Reader from the App Store. It would be wrong to continue to sell
an app that only functioned in a limited manner, even though the App Store is
far and away my best form of marketing.

So what do I suggest Apple does? I think they need to allow apps that are not
sand-boxed. However these apps could come with a warning before installation. In
Mountain Lion, the new security feature called Gatekeeper allows you to specify
the level of security you want when installing apps. Currently the options are
to allow apps downloaded from:

Mac App Store

Mac App Store and identified developers

Anywhere

They could split the first option in two and allow

Mac App Store sandboxed

Mac App Store any

One further wrinkle is iCloud. Apple is encouraging users and developers towards
iCloud data storage and sharing. But only apps in the App Store are allowed to
use iCloud.

So it will be interesting to see how this plays out. Obviously Apple is not
going to care if a tiny developer like me leaves the App Store, but if enough
high-profile developers leave, then there will surely be some consideration
given to the problem.

A Knight's Move Released

UPDATE: September 2016 - A Knight’s Move for iOS is no longer available.
A Knight’s Move for Mac is still supported.

“A Knight’s Move” is a fun, addictive and simple puzzle game based on the
movements of chess pieces. Your goal is to move your white knight across a board
to a target square using the same movements as a knight in chess. Pawns may
block your way, while enemy bishops, castles, knights and the queen may try to
stop you.

The game is available for iPad, iPhone and iPod Touch from the iTunes Store and
requires iOS 5.0 or later. The Mac version is available from the Mac App Store
and requires OS X 10.7 or later.

Perfect for when you have a few minutes to relax, like on the train to work,
during your lunch break or during a boring lecture or class (Kids: don’t take
advice from randoms, but you can turn the sound FX off. Just sayin’), “A
Knight’s Move” will keep you coming back for “Just One More Go”!

Once you have played the tutorial pack, you can move on to the other puzzle
packs. Each pack comes with 25 more puzzles and there are many different packs
allowing you to select easy puzzles, challenging puzzles or variety packs, some
with themes.

A Knight's Move

A Knight’s Move is a puzzle game where you have to move your knight across a
board to a target square using the same movements as a knight in chess. Pawns
may block your way, while enemy bishops, castles, knights and the queen may try
to stop you.

Get from the starting position to the target in the shortest possible number of
moves. Score stars based on the moves taken. If you need help, take a one star
penalty to show all possible moves. If you really get stuck, after several tries
the Cheat button allows you to see a solution, although that will cost you all
your stars.

Choose your preferred board and chess pieces.

FAQ

Q. Does the time I take to solve a puzzle count against me?
**A. **No - the number of stars you get depends solely on the number of moves taken.

Q. Are there any penalties for using Undo or Restart?
**A. **No - both Undo and Restart wind back the number of moves, so are not counted
towards your final number of moves.

Q. What are the best techniques for solving a large puzzle?A. Sometimes it is easier to work backwards. Work out which squares get you to
the target safely and see if you can work out how to get to one of them. Another
technique is to check all the possible moves and see how many can be eliminated because
of danger or because they don’t lead anywhere except back to where you started. Just
remember that trying and failing doesn’t count against you, so give it a go.

Q. What if I need help with a puzzle?A. The first way to get help is to turn on “Show Moves”. This puts green circles
on any square that your White Knight can reach next move. It does not indicate whether
these squares are safe, but just shows you all legal moves. This option costs you
a one star penalty but you can always do the puzzle again to try for three stars.

Q. What if I think a puzzle is completely impossible?A. All the puzzles have at least one solution. If you have tried and tried, using
Restart or being captured at least 5 times, the Cheat button will become available.
Using the Cheat button will show you a possible solution but will mean that you can
never get any stars for that puzzle.

Q. You’re kidding, right? No stars… ever… just because I cheated?A. OK, I’m kidding, but the way out of this is deliberately hidden and inconvenient.
If you go to Settings or Preferences, you can reset all the game scores which clears
all records of stars won so far, allowing you to restart completely. If you reset
the scores three times in a row, this will also clear all records of cheating.

Q. I think I solved a puzzle in fewer moves than the minimum moves shown.A. Great! Please take a screen shot of the puzzle and annotate it to show your
moves. Email it in to sarah@troz.net so that I can edit the puzzle for the next update.

Easy access to the Library folder

In Mac OS X 10.7 (Lion), Apple decided to make it more difficult to access your
Library folder, presumably to stop people doing stuff that made apps crash. But
as a developer, I need access to my Library folder a lot. I need to check that
preferences are being saved correctly. If I have an app that uses the
Application Support folder, then I need to be able to check it. And for
sand-boxed apps, they keep all their data in the Containers folder inside the
Library.

You can easily get to the Library folder by holding down the Option key while
choosing the Go menu in Finder. This adds Library to the menu and you can get to
the folder that way. But this is not as convenient as single-click access from a
Finder window, so here is my preferred method.

Use the Option key and the Finder’s Go menu to get the Library folder open in a
Finder window. Switch this window to column view, which will display the Library
folder (slightly greyed out) in the first column. Drag this Library folder to
the side bar of your Finder window. Now it is there all the time, in every
Finder window that is showing the side bar.

I have read about various Terminal tricks to get the Library to show up, but
every system update seems to turn it off again. This technique doesn’t involve
anything except the Finder’s side bar preferences and so far (I’m now up to
10.7.4), it hasn’t needed to be reset after any update.

Man Reader update coming soon

Man Reader launched on the Mac App Store a couple of days ago and yesterday I
got an email from a purchaser who reported that Man Reader was not displaying
the man pages for MacPorts, even though he had the paths set up correctly.

I installed MacPorts to check this out and ran into the same problem. Running
the command “man port” in Terminal worked fine, but “port” did not appear in Man
Reader’s list.

Man Reader uses the “apropos” command to list all available man pages, so I
tested it next. When I found that it was not listing “port” either, I thought I
had discovered the problem. OS X offers two commands for searching for man
pages: apropos & whatis. The database files used by these commands are updated
weekly by one of the periodic system commands. I manually ran this update
command using:

sudo /etc/periodic/weekly/320.whatis

This did part of the job, as the apropos command when used in Terminal now
contained the MacPorts man pages. However Man Reader still did not show these
man pages.

Reverting to the Console log, I found that this was a sand-boxing problem. The
Mac OS X sand-box was preventing access to the man.conf file (which tells where
to look for man pages), and the whatis database file containing the new data. I
assume that without access to these files, the default locations for man pages
were still searched, but no non-standard locations were being searched.

I have just submitted an update to the App Store that still uses sand-boxing but
requests temporary read-only access to the file system to read these files. If
Apple rejects this, then I will release a version without sand-boxing.

Either way, you can be assured that the matter is being dealt with and the next
update, whether sand-boxed or not, will allow access to all man pages.

New features:

Making a Mac Screen Saver

Having just completed the my first screen saver for Mac - the Time In Words
Screen Saver, I thought I would share some of the experiences. I am using OS
X Lion (10.7) and Xcode 4.3.2

The first thing is to create a new project in Xcode using the Screen Saver
template:

Xcode sets up a project for you with everything you need for a screen saver
module. Start editing the ScreenSaverView.m file. The most important method here
is animateOneFrame.

This is called every time the animation time interval elapses. This interval is
set in initWithFrame:isPreview:. I have seen some debate online as to whether
the drawing should be done in the animateOneFrame method or in the drawRect
method. I chose to use animateOneFrame because they are both called when the
screen saver starts which can lead to an unpleasant flicker.

Now it is up to you to decide what to show in the animateOneFrame method. For
Time In Words, I assembled the data as a string, created a dictionary of text
attributes, calculated the location where I wanted to show the text and used
drawAtPoint:withAttributes: to display it.

There are a couple of important tricks when working out locations: firstly, you
will need to know the bounds of the screen saver area. This will vary depending
on the monitor, screen size or whether the screen saver is appearing in the
preview window in System Preferences. The screen saver view has a method that
does this work for you.

NSRect viewBounds = [self bounds];

The next trick is that you are most likely going to need some random numbers.
Again, the screen saver framework supplies these to you in several forms. I used
SSRandomFloatBetween but there are others. Check the documentation.

I ran into an oddity in System Preferences that made testing a bit tedious. I
built the screen saver module and double-clicked on it to install into System
Preferences. That worked fine, but when I made some changes and repeated the
process, the original screen saver was still in place. I found that I had to
quit System Preferences each time. Deleting the old version of the screen saver
was not necessary, but quitting the System Prefs app was essential.

So that gives the basic screen saver module but with no options. Adding options
is not difficult, but as always, there are a few things that are not obvious on
first glance.

Add a xib file to your project: I used a window template. Then change the
window’s class to NSPanel and configure it as shown:

Set the File’s Owner class to the class of your Screen Saver view. In your
ScreenSaverView.h file, declare a property for this new panel. e.g.

@property (assign) IBOutlet NSPanel *optionsPanel;

@synthesize this in the ScreenSaverView.m file. In the xib file, connect the
panel to this outlet.

The hasConfigureSheet and configureSheet stubs are already there for you,
but you can replace them with these versions.

Go back to the xib file and drag in a button to close the options panel. Connect
it to the closeConfig: action.

Save everything, build, install in System Preferences and test. Firstly, the
“Options…” button should be enabled. Clicking it should open your panel as a
sheet, and when you click your button, the panel should close.

If that doesn’t work, check the class assignments, the connections, the settings
for the NSPanel and the code in that order.

Once the panel is opening and closing as required, you need to add the ability
to store and retrieve the settings. Instead of using NSUserDefaults as you would
in a standard Mac app, there is a special class call ScreenSaverDefaults for
screen savers. It needs a unique module name, so I used the bundle identifier.
For my Time In Words screen saver, this is
“net.troz.Time-In-Words-Screen-Saver”. I defined a constant to hold this as a
string, so I could use it anywhere I needed.

In the initWithFrame:isPreview: method, I got a reference to the screen saver
defaults for my screen saver and registered the defaults. I am never very sure
about the need to do this, but it is supposed to be a good practice.

One last thing: if you want to distribute the screen saver, you will want to
create an archive, possibly code-signing with your Apple developer ID to allow
for Mountain Lion’s up-coming Gatekeeper security system. I code-signed the
project and built an archive, but when I clicked “Distribute” in the Organizer,
the only appropriate options was “Save Built Products”. I selected this option
and ended up with a series of folders inside folders, with the screen saver
module in about the fifth folder down. I don’t know why the module gets
distributed like this, but I pulled it out of the folders and it worked fine.

And that’s about it. A lot of this stuff is online or in Apple’s documentation,
but there are enough oddities to make it worthwhile gathering together all that
I learnt while making this screen saver.

Man pages are available for the Unix commands used mostly in Terminal or when
shell scripting. These man pages are normally displayed in Terminal using the
“man” command e.g. “man man” gives you the man page for the man command.

However there are problems with this: the man page is displayed to you in your
Terminal window page by page and when you have got to the bottom, you have to
know to press ‘q’ to get out of the man page display, at which point it
disappears completely. Hope you have a good memory!

There are various tricks to get around this: opening it in a separate window,
piping it to Preview as a PDF, listing it as a single page etc, but none of
these are really convenient, which is why I wrote Man Reader. Basically, I
reckon that if I want a utility, then there must be other people who would want
the same thing.

Man Reader assembles a list of the commands with available man pages on your
system - this will vary according to what developer tools you have installed.
These commands are listed for you and you can click on any one to display the
man page for that command.

Man Reader Features:

List of all available man pages on your system.

Show only a section of the pages.

Search for a man page by name.

Display man page in text or HTML (different pages look best in different
formats).

Step back & forward through recently viewed man pages.

Live links to ‘See Also’ entries.

‘Sticky notes’ at the side to jump to sub-sections in a page.

Choose a font and size for the display.

Convenient buttons in the toolbar allow quick access to commonly used
utilities.

Sand-boxed for OS X Lion & later.

Man Reader version 1.8 changes (23 Oct 2016):

More complete search for man pages, including in third-party IDEs.

Fix for glitch when displaying previously selected page on launch.

Man Reader version 1.7 changes (10 Oct 2016):

Updated for macOS Sierra.

List of pages now uses alternating colors even if not using the defaults.

Minimum supported system version raised to 10.11.

Minor display glitches fixed.

Man Reader version 1.6 changes (13 Jul 2016):

Much improved searching for available man pages, including permissions fix for
some pages.

Fixed error with new search term being over-written.

Sand-boxed version now works just as well as the non-sand-boxed so please
switch back to this version.

Like Time In Words for iOS and World Time In Words for Mac, it
displays the time and date in plain words which are easy to read and comprehend.
While it only shows a single time and date, this can be configured to show your
local time & date or any available time zone. Since the App Store does not have
a section for screen savers, the Time In Words screen saver is available as
a direct download from my site. Click the link or the icon above to download the
screen saver as a zip file. If the zip file does not open automatically,
double-click the file to unzip it. Then double-click the “Time In Words Screen
Saver.saver” file to install the screen saver in your System Preferences. You
will be asked whether you want to install it for the current user only or for
all users. Selecting “All Users” will require you to enter your password, so I
recommend just installing for the current user.

Scroll to the “Other” section of the list of screen savers and click “Time In
Words Screen Saver” to activate it. Sometimes the installation leaves the screen
saver selected but not active. If this is the case, select another screen saver
and then click back on Time In Words.

By default, your local time & date will be displayed. To select a different time
zone, click the “Screen Saver Options…” button to display the following:

Click the “Show Alternate Time” radio button to enable the time zone list. As
with Time In Words for Mac, you can type part of a city name in the search field
to find a zone quickly. Select the zone you want to use and click “OK”. The
preview will switch to showing your newly selected time zone.

For anyone interested in the source code, here is a download link: Time In
Words Screen Saver Xcode project. This was written using Xcode 4.x so is
rather out-dated by now, but may prove useful to others wishing to start writing
their own screen savers.

Support for older operating systems

Working out what operating systems to support in your software is always a
difficult decision. I only program for Mac & iOS systems for starters. This is
because they are the systems I use and understand. I am not interested in
expending the time & money needed to program and test my software for other
systems.

Within the Mac & iOS ecosystems, there is still the decision of which versions
to support. Partially, this is based on the usage statistics of each version. I
found a site that segments the current Mac market:
Distribution
of Mac OS X versions. This tells me that OS 10.6 & OS 10.7 between them have
83% which makes 10.6 a good cut-off point.

Distribution of iOS versions is harder to discover, but I found a post that did
a good job of analysing the statistics that are available:

pxldot (iOS Ebb and Flow). According to this post, by March 2012, iOS had
about 75% with the remainder being almost exclusively iOS 4.

So based on statistics alone, it makes sense to support Mac OS X 10.6 or later
and iOS 4 and later. However this doesn’t cover all the relevant issues. Another
important factor is new techniques and APIs introduced in Apple’s developer
tools.

In iOS 4, Apple gave us ARC - Automatic Reference Counting - which basically
removes the tedious job of memory management. This was especially painful in iOS
apps where there is no garbage collection. The Long Weekend Website has an
excellent summary of ARC - what it is and how to use it. Since this only
excludes iOS 3 or earlier, there is no issue using this for all iOS projects.

But now Apple has extended ARC to Mac apps as well, but only for apps built to
run under 10.7 or later. Even though Mac apps could use garbage collection to
remove some of the burden of memory management, this had its own inefficiencies
and overheads. So in my case, I have decided that all future apps will require
10.7 to take advantage of ARC. Existing apps will stay as is - requiring 10.6 or
later. With 10.8 not that far away, the usage statistics should follow this
trend.

Back to iOS, there is another new feature of Xcode that is really too attractive
to ignore and that is story-boarding. This is a graphical way of laying out the
navigation logic for your app and providing segues between different views. Ray
Wenderlich has a good introduction to storyboards. So this means that my
future iOS apps will all require 10.5 or later.

One final factor is testing. You really need to have a device running each
version of any supported operating system. I would rather concentrate on getting
the best result for users of the latest versions that spend my time tweaking for
older systems. With iOS, Apple makes it amazingly easy to update to the latest
version. With Macs it costs money which is always a barrier, but technically,
the App Store is making updates easier to apply.

Time In Words & the new iPad

The new iPad has a Retina display, meaning that the pixel density is much
greater. For some apps, this is a problem as their graphics are now scaled and
look pixellated. However Time In Words is very simple. It uses standard fonts
and interface widgets with no images or external graphics apart from the icon.
The icon may not look perfect on a new iPad, but the display itself should look
really great.

I had a report from one user that Time In Words will not work at all on his new
iPad. Unfortunately, the email address supplied did not work, so I was unable to
contact this person directly. If you are reading this, please contact me again.

The person having the problem did not specify exactly what the problem was, so I
don’t know if the app will not start, or if it is not displaying correctly, or
if it is showing the wrong times or what.

However I suggested two things to try, and I will list them now in case anyone
else is having issues:

Try deleting the app from your iPad and then re-installing from the App
Store.

Do a complete reboot of your iPad in case it is running low on memory.

Hopefully one or both of these ideas will solve any problems. They are both good
general tricks to try with any problem app.

iPhone 4 Home Button

My iPhone 4 is now 18 months old, and it’s Home button is starting to feel the
strain. These buttons have been used much more than originally intended, with
the new multitasking required double-presses, not to mention access to the
camera etc. So basically , it is wearing out.

The phone is out of warranty and there is no way I am going to pay for an
expensive repair when my current phone contract will expire later this year, and
hopefully the iPhone 5 will be ready for me then. And a cheap repair or DIY is
too risky.

I saw a post comparing the physical structure of the home buttons on iPhone 4 &
4S. Unfortunately I cannot find the link now, but it showed that the actual
hardware has been made a lot more robust since the iPhone 4 was released, so
this should only be a short term issue.

I read a article suggesting the use of WD-40 for a mis-behaving Home button.
This is a TERRIBLE idea! Do not spray a penetrating oil into your expensive
electronic device. For starters, it don’t believe it is a friction problem - I
think the mechanism is just wearing out.

Some people recommend recalibrating the Home button as shown in this post from
idownloadblog.com. I am a bit sceptical about this. I tried it, but I can’t
see that it did anything. Maybe if your problem is software rather than
hardware, then it will do some good. Anyway, unlike the WD-40 trick, it can’t do
any harm.

Finally, on to the workaround. If your iPhone button is really unreliable, but
you are not ready to repair or upgrade, then you can use the Accessibility tools
to get a software Home button on the screen.

Go to Settings - General - Accessibility. Scroll down to “Physical & Motor”.
Turn on AssistiveTouch.

When you back out of Settings, you will see a white blob somewhere on your
screen. This can be dragged to any location around the edge of the screen, so
you can always move it out of the way in any app.

Tapping on the white blob gives you an overlay view with four options, one of
which is Home. Tapping this is exactly the same as pressing the physical Home
button. So with this and the power button, you can do everything, even if the
Home button stops working completely.

Thanks to Tom at our local Apple Store (Robina, Queensland, Australia) for this
tip.

World Time In Words for Mac

World
Time In Words for Mac version 3.2 is now available through the Mac App
Store. This version adds support for macOS Mojave dark mode.

Version 3 changed the name from “Time In Words” to “World Time In
Words” as an acknowledgment that the major feature of this app is converting
time between different time zones. This update adds the ability to show digital
time if you need greater accuracy - just hold down Option as you open the menu.
I have also added the ability to show 24-hour time in the menu bar.

World Time In Words runs as a menu bar utility app that displays your current
time and date in words. Optionally, it can be set to display a number of time
zones, in plain English so it is always clear which day is being referred
to. It shows the time in words in your menu bar all the time if you like, and
now offers a convenient way to work out what the time will be in other zones at
a specified local time.

The first time you run the World Time In Words app, it will appear in your menu
bar and pop down a menu that looks like this:

Selecting Preferences… will take you to a window like
this

Type in part of a city name in the search area
to find that city and its time zone. Drag or double-click a line in the table on
the right to move a time zone to the list on the left, which shows the time
zones that will appear in the menu. Drag a line out of the list on the left to
remove a zone, or double-click the unwanted line. Drag and drop to re-arrange
the zones in the selected list.

Once you have selected some time zones, your menu may look like
this:

Note that the menu will indicate which time
zones are currently in daylight savings time.

Version 3.0 adds the ability to see all the time digitally if you have a
temporary need for greater accuracy. Hold down the Option key as you click in
the menu title and the menu will appear like this:

To specify what will be displayed in the menu bar, you can toggle “Show time in
words as menu title”. If this is checked, you have two other methods for
adjusting what you will see. Select your preferred accuracy: “To closest 5
minutes” or “Precise”. Use the popup menu to select a time & date format to show
in the menu bar. You can also choose 24 hour time for the menu title if you
prefer.

To see what time it will be in your selected time zones at various hours during
your day, choose “What time will it be when…” from the menu. Move the slider
to different hours in your local zone and read what the corresponding time will
be in your preferred time zones.

If you want to make World Time In Words start automatically whenever you log in
to your Mac, check the “Auto start…” checkbox. This uses Apple’s new methods
of adding sandboxed items to the login startup list which has two consequences:

World Time In Words will not show up in your Login Items if you go to System
Preferences

The auto-start will only work if the app is installed in your Applications
folder.

While I do not think the second item is a problem, since the App Store
automatically installs into your Applications folder, I disagree with the policy
enforced in the first item. It means that if you wish to un-install World Time
In Words, you should ensure that you have turned off “Auto start…” first, as
there is no easy way to do this from outside the app.

However, World Time In Words is sandboxed, so it’s data and settings are kept in
their own container and isolated from other apps for better security.

If you are having any problems with World Time In Words, or you have any
suggestions for future improvements, please email me.

Interface options for selecting time zones

As part of the design for [Time In Words for Mac][1], I had to work out the
interface for selecting time zones. With [Time In Word for iOS][2], I used
picker wheels which are excellent for selecting hierarchical data. On the Mac,
there is no such thing as the iOS picker wheel and so I had to consider what to
use instead.

When you ask the system (Mac or iOS) for the available time zones, you get a
list of names like this:

This seems obviously designed for a hierarchical display with the major regions
as a first selection, filtering down to the cities in that region, making
selection a two-step process. With the picker wheel in iOS, that is what I did.
The first wheel selects the region which then populates the second wheel with
the relevant city names. It makes it quick and easy to select a zone.

I always prefer to use standard user interface objects because people are
familiar with them, they automatically update with the system, and there is much
less chance of the App Store rejecting the app. So I scrolled through the
available Mac options and came to NSBrowser. This is basically what Finder uses
when in column mode.

I created an NSBrowser object, worked out a way to populate it and tested. It
was incredibly slow! The list of regions appeared when the window opened, and
that was no problem. Then I clicked a region and the first set of city names
appeared instantly. But subsequent selections took about 3 seconds to appear.

I added some timing tests and my data gathering was taking about 20
milliseconds. The log thought the browser had updated within about 100
milliseconds, so I guess the rest of the time was some redraw issue.

Apple provides a large number of sample projects so I downloaded one that used
NSBrowser. It seemed fast and responsive, so I duplicated it’s different method
of assembling the data and tried again. No luck - it was as slow as before.

I am sure that if I kept at it, I would eventually work out what was causing the
bottleneck and make NSBrowser work - after all, Finder is responsive enough,
even if not great. But in the end, I decided that the advantages to using this
form of interface didn’t justify the time spent, so I went with a simple table
and a search field.

It is fast to populate, responsive to searches and didn’t take long to set up.
So I am happy, although still perplexed about NSBrowser. It is on my to-do list
of things I want to work out one day.

[1]: /time-in-words-for-mac/ [2]: /time-in-words/

Scroll bars in Mac OX 10.6 and 10.7

With the introduction of OS X 10.7 (Lion), Apple removed the obvious scroll bars
from windows and replaced them with a much more subtle scroll indicator, that
only appears when you are actually scrolling. This was designed to match the iOS
scrolling, as was the swap of scroll direction which makes much more sense if
you use a trackpad.

With the upcoming Time In Words for Mac, I have a Preferences window to
allow selection of time zones to display in the menu. The app will be compatible
with 10.6 or later. Under 10.6, the scrollbars are always visible and this is
what the Preferences display looks like:

This may change, but the basic layout is there. As you can see, I have a
3-column table listing all the available time zones, with the final column right
justified.

Under 10.7, this doesn’t quite work:

I had to grab this screen shot quickly after swiping the trackpad, but you can
see the problem. When not scrolling, the scroll indicator is hidden and the
right column is fully visible, but when dragging the scroll indicator appears on
top of the right-justified entries in that column.

So now I am not quite sure what to do. Here are the options I have considered:

Left or centre-justify the text in the final column.

Add some spacing at the end of each line so that the scroll indicator appears
in blank space.

World Time In Words for iOS

World Time In Words is a clock and time converter app that takes you away from numbers and shows you the time as a complete sentence. No more worrying about whether it is morning or evening or whether it is yesterday, today or tomorrow in some other part of the world.

Do you plan on phoning an overseas friend in the middle of the night? How about scheduling an online meeting with people in different time zones? Or even checking what time the next big keynote will start in your time?

Set up World Time In Words up with all the time zones you need to check. Scroll through the list to see the local time in each of your selected zones shown as a sentence. This is easier to comprehend and much less prone to error.

If you need to plan a meeting or phone call, tap “What time will it be…". Use the slider to adjust the hour in your local zone and the corresponding hour in your selected world zones will appear.

Tap the “+” button to add or delete time zones.

Your top three selected time zones can also be added to your Notification Centre as a widget. Click Edit and drag to change the order of time zones in the table to decide which ones appear. Then swipe to your widgets page, scroll to the bottom and click the Edit button to add the Time in Words widget.