Brave Location Mobile Apps and Web Solutions

Count The Days Left

Count The Days Left

Count The Days Left is a simple, elegant iOS app that does just one thing - counts the days between the start and end date of an event or project, and how far along you've progressed so far.

It's optimised around your work tasks, as you can decide to count just weekdays if required.

I've also added a nice widget for the Today notification screen, for quick access to your progress, as well as an Apple Watch app and complication.

The app was written as part of a "develop in the open" project, so if you're interested in the code it's available on GitHub, or read the blog posts below ...

Download on the App Store


Blog Posts about Count The Days Left:


Why I put ads in my app

I recently released a version of my Count the Days Left app which included ads for the first time.

I thought long and hard before doing this, so I thought it might be interesting to document how I worked through this decision, as it’s pretty typical of the trade-offs independent software developers have to make.

How I make money

I’ve been a commercial software developer for nearly 30 years now (wow!), including over 10 years working at Microsoft (MSN/Bing/Skype).

Right now, I split my time between:

  • Contracting out my skills to businesses for fixed-term projects
  • Building mobile apps and websites for businesses
  • Developing my own iOS and Android apps for both pleasure and profit

In 2017 I’m trying to diversify my business more, so the 3 areas above contribute more equally to the bottom line.

Currently, by far the biggest part of my income is working on contracts for other people, and I’m trying to generate more independent streams of income so I can be more in control of both my time and where I work.

Why I built Count The Days Left

I built the app for a few reasons, but mainly:

  • I wanted to showcase my skills to generate potential business
  • I wanted this app for myself, and most of the alternatives in the App Store were either ugly or not quite what I wanted

For the first point, I’ve blogged extensively about how I’ve built the app, as well as open sourcing the code on GitHub so potential customers can see my work.

The app has been pretty successful in meeting these aims, and has definitely helped in generating business (although it’s hard to measure the actual monetary value of this).

As you’d expect from a simple and niche app, it doesn’t have masses of users - daily users are definitely in the hundreds rather than the thousands.

In fact, some of the features (showing the days left as an icon badge, the Today widget, plus the Watch complication and app) are designed so the users don’t actually need to open the app every day, but I’m pretty proud of how it’s turned out.

Monitising the app

For any iOS app, there are three main ways of making money from an app:

  1. Charging to buy the app
  2. Adding an in-app purchase or subscription, probably to unlock additional functionality in an otherwise free app
  3. Adding ads

Now, unfortunately I suspect there is very little chance I’d sell many copies if I decided to charge for the app. There are so many free competitors to this particular app, and even if my app is better than them - and obvioiusly I think it is :) - it’s very hard to see how many customers would agree.

People are now so used to getting high-quality free software, generally from venture capital backed companies who are happy to lose lots of money to capture large audiences in the hope of monitising that audience later. That makes it a very hard sell to convince people even to spend $0.99 on an app that might provide them with lots of value.

Personally I’m happy to pay for good software, especially from independent software developers who are doing great work.

However I completely understand why most people don’t think in that way, and as I can’t see the situation ever changing, for most consumer apps I can’t see there’s much point in even charging a very small amount.

Now this particular app only really does one thing (although hopefully it does it well!), so I can’t see any sensible way of adding “pro features” to be unlocked by an in-app purchase.

I guess I could try a patronage/shareware model, and ask for money to support the app? I’m not sure that would actually generate any money without some sort of persistent nagging which I don’t think I’d be happy with.

This probably gets to the nub of my problem with all of this discussion. I’m not sure if it’s a British thing, but the conflict between needing to get paid and somehow seeming to be only doing it work the money is complicated.

I do want people appreciate and enjoy the app, and somehow this should be separate from the dirty business of getting paid.

So this just leaves adding ads.

Tasteful Ads?

I didn’t want the app’s main screen to show ads at any time. I think its’ main selling point is it’s a tasteful and good-looking app (especially compared to some of my competitors), and slapping an ad there would completely negate that.

Therefore only other place left to put the ads is on the settings page, where you change the title, start and end dates of what you’re counting down to.

I’m reasonably happy with this compromise, although from a pure money-making point of view this page is not viewed very often, as the users only go thereevery time they start a new countdown.

I’m using Google to provide the ads via AdMob, and have customised them to be text-only and in a color that matches the rest of the app. At least in that way they are not too jarring, and fit in as well as I can make them.

As you can see from this example, the way the ad looks is OK (even though the content is frankly a bit shit)

Screenshot of the Ad

Is it worth it?

In the first week, I’ve made a few pennies - slight more than I expected, which was very little be honest!

However, I’m generally happy I’ve done this. I think it’s important all software developers get paid fairly for their work, so turning the tide against the idea all software should be free - even the the smallest way - is OK.

Probably.

Obviously giving Google even more data is not “free” for my customers, as they are now paying for the app with their information. I’m not 100% happy doing that, but as I’ve hopefully explained here, it’s a complicated trade-off.

Feel free to contact me via Twitter at @yeltzland if you have any thoughts on any of this.


Moving 'Count The Days Left' to Swift 3

Version 2.3 of Count The Days Left has now hit the App Store for your viewing pleasure.

I finally got around to upgrading the code to Swift 3. The XCode migration code did a reasonable job with the syntax changes, but missed a few things around interface changes - especially in the WatchOS code - that I had to fix manually.

I also fixed a very minor logic error in the date calculation in the settings page. Quite amazing it had been sitting there in plain sight for a long time without me noticing it.

Not much more to do in the app right now, but maybe WWDC in the summer will bring some exciting new areas in which to play in?


Building an iMessage app

Now that iOS10 is out I thought it was about time I built an iMessage app for Count The Days Left.

To be honest, it took very little time once I’d written a script to generate all the “progress images” I needed i.e. 100 images that show the percentage completed in the progress bar.

The UI is just a standard Storyboard + UIViewController for layout, and then hooking up an event handler to a ‘Send Message’ button (see below for details).

    @IBAction func sendMessageTouchUp(sender: AnyObject) {
        if let conversation = self.activeConversation {
            let now: NSDate = NSDate()
            let model: DaysLeftModel = DaysLeftModel()
            
             // Make a new layout object
            let layout = MSMessageTemplateLayout()

            // Set the caption on the layout
            layout.caption = model.FullDescription(now)
            
            // Set the correct image on the layout
            let percentageDone: Float = (Float(model.DaysGone(now)) * 100.0) / Float(model.DaysLength)
            let intPercentageDone: Int = Int(percentageDone)            
            let imageName = String(format: "progress%d", intPercentageDone)
            layout.image = UIImage(imageLiteral:imageName)
            
            // Make a new message and set its' layout
            let message = MSMessage()
            message.layout = layout
            
            // Insert the message into the conversation
            conversation.insertMessage(message, completionHandler: { (error: NSError?) in
                print(error)
            })
        }
    }

Other than the usual fun with making everything look OK with Storyboards and Auto Layout at the different screen sizes, it all worked out pretty well as you can see from the screenshot below:

Count The Days left iMessage app screenshot

I’m not sure how useful this will be, but it was very easy to build and I’m pleased with the result.


Getting Ready For iOS 10 Widgets

It’s summer, which means updating all the Brave Location apps for the new version of iOS.

Thankfully this year the UI changes weren’t too big, and the real work was because of how the Today widgets are changed in iOS 10.

In iOS 9, the widgets are on a dark background, so it makes sense for the text to be generally white. Here’s how my stunning well-designed widgets look in the Today section on my iPad running iOS9 …

iOS9 Today widget

Now in iOS 10, the widgets are much more accessible - can be accessed directly by right swiping even on the lock screen - but the design has also fundamentally changed. The background is now a light, semi-transparent color by default, on which obviously the white text of the existing widget design is basically unreadable.

Now I didn’t want to have an iOS10 only release ready, as all of my apps currently target iOS 9.0 and above and I want to keep it that way for a while.

So what I do at runtime is detect whether we are iOS 10.0 or above by the following code snippet:

let ios10AndAbove:Bool = NSProcessInfo.processInfo().isOperatingSystemAtLeastVersion( NSOperatingSystemVersion(majorVersion: 10, minorVersion: 0, patchVersion: 0) )

I can then set the background and text colors of the widgets to appropriate for iOS 10 when necessary, buy keep the “traditional” look and feel on what will soon be legacy versions.

Quite happy with the way it’s turned out, even though I say it myself.

iOS10 Today widget

Updates are should all be in the App Store shortly (in case anyone else is running the iOS10 beta), and for everyone else in September I assume!


More Reliable Background Notifications

I’m really happy with the “Show the days left as a counter on the app’s badge” feature on Count The Days Left, but unfortunately due to the way Apple implements background fetches makes it a little unreliable in staying up to date.

The latest version of the app fixes this by using push notifications to regularly wake the app to update itself.

Background fetch is unreliable

The problem was that I was using the background fetch feature to run the app in the background every so often, and when it runs update the number of days left on the badge.

However, the frequency the background fetches are run is completely down to the operating system. Now as far as I understand, iOS will allocate background processing time based on how often the app is used.

Obviously this causes a bit of a logical error. If the user enables the badge to show the number of days left, they are a lot less likely to open the app - which obviously means it’s less likely to run in the background, so is more likely to be wrong :(

Push notifications solve the problem

The best way of fixing this issue is to send out regular push notifications to the app, so it’s guaranteed to wake up and refresh the badge count.

In an earlier post I wrote about how I’ve found Azure the easiest way to set up the server side of things, and I did the same here.

I then send out notification with "content-available": 1 in the payload, which will not show anything in the Notification Center to the user, but the app will wake up in the background and run the code to update the app.

Obviously this means setting up some (minimal) server infrastructure to manage this. I’ve written a NodeJS script that triggers the push notification via the Azure API, and setup a cron job to run the script every 6 hours.

So far for me this has worked a treat, and I’m much happier with the solution even though it took a bit more work.

The new version of the app (v2.0.4) is available on the App Store right now.


Swift and Watch Performance Improvements

One slightly strange and irritating issue with Count The Days Left is the app has a small but noticeable delay on startup.

I added a ton of instrumentation to help figure out what was going on, and was then able to make some micro-improvements which have helped a little. However this small decrease in loading time makes the app FEEL a lot quicker on startup.

Changes made:

  1. Move the Watch communication initialization code off a background queue onto the main thread
  2. Removed an additional and unnecessary call to update the badge number
  3. Moved updating of control settings into viewDidAppear() from viewWillAppear()
  4. Optimised watch app view updating logic to do minimum work necessary

The first point was unexpected, but after measuring the actual speed of the code the overhead of spinning up a new thread and running code in parallel was not actually worth doing. As ever, measurement trumps expected outcomes.

The third point clearly didn’t really any difference to the amount of code to be run, but perception is all and it feels a little faster.

The final point is obvious - the Apple Watch is very underpowered, so doing the absolute minimum amount of work at all times is essential.

Summary

The startup time is still a little slow - and my unproven suspicion is that Swift apps take a little longer to initialise in general anyway - but I’m a lot happier with it now.

As ever, more details can be found on the GitHub repository where all the code for the app lives.

I’ve just submitted v2.0.3 to the App Store for review, so unless we have any shenanigans as before hopefully it will be available in the next few days.


A Minor Change and we're through the App Store Review

So I finally made some progress after my rant last time and I’ve finally released the latest version of Count The Days Left to the App Store.

What I changed

The “problem” was that the watch complication was deemed too similar to the battery complication. This was because it’s using the CLKComplicationTemplateCircularSmallRingText template that is one of the few - and pretty restricted - template options available to a developer

Here’s a screenshot from my watch, with the battery complication in the center and the “problem” Count The Days Left one on the right:

Watch screenshot

I decided to make the most minimal change possible - simply change the style of the progress ring from Closed to Open

If you look closely, you can see the massive difference this made below:

Watch screenshot

I think this is actually a better choice, as the very small “open” gap at the bottom of the circle matches the main UI.

Anyway after a worrying delay of 3-4 days while the app was “In Review”, the change was accepted and version 2.0.2 has FINALLY been released!

Moral of the story is …

Never underestimate how crazy the app approval process can be!


Inconsistent and Illogical App Store Review

I’ve not been able to release the changes to Count The Days Left mentioned in my last post because of a very frustrating review from Apple’s App Store reviewers.

Review feedback

After waiting over a week for the new version to be reviewed, I received notification that it had been rejected. I assumed this was because of the XCode bug I documented in the last post, but it was actually the following:

8.3 - Apps that appear confusingly similar to an existing Apple product, interface, or advertising theme will be rejected

8.3 Details: Your Apple Watch app contains features that mimic native iOS interfaces or behaviors. Specifically, the Complication used for your Apple Watch app mimics that of the native ‘Battery’ Complication design and interface.

Next Steps: Please revise these features to make them distinctly different from the iOS behaviors and interfaces to avoid causing user confusion.

Illogical

Now although the reasons given for the rejection are factually correct, they really don’t make any sense.

Here’s a screenshot from my watch, with the battery complication in the center and the Count The Days Left on the right:

Watch screenshot

However there is a very good reason it looks the same - it’s using the CLKComplicationTemplateCircularSmallRingText template that is one of the few - and pretty restricted - template options available to a developer.

Almost certainly the battery level complication is using the same template, which makes a lot of sense. If you have a “progress” number you want to show - which both the battery and my app do - this is the logical template to use.

Obviously if using this template in your app isn’t going to make it through an app store review, it doesn’t make any sense to allow it in the complications SDK.

However the real answer is that using this complication shouldn’t be rejected by the reviewers. I’m obviously not trying to pretend my app is a battery level complication, and when the user is selecting their complication which one is which (as you can see below):

Watch screenshot

It’s this level of over restriction of their platform that can make it very, very frustrating developing for Apple’s platforms. I’m not advocating a free for all on allowed apps, and their needs to be quality control to not allow apps which abuse user’s data or the like.

However even the intent behind this rule doesn’t make any sense. The fact that my app’s complication looks like another one doesn’t harm the user in any way at all, and if they want to use both at the same time then why shouldn’t they?

Inconsistent

If you’ve been following along as I’ve developed this app, you’ll have spotted the other flaw in Apple’s system.

The complication design hasn’t changed at all since the previous version which was deemed acceptable in previous reviews!

What to do next

I obviously appealed against the review to the App Store, giving the arguments I made above but it still got rejected.

I’m not sure how best to move forward now. I guess my options are:

  1. Resubmit the app again and hope this time I get a more favourable reviewer
  2. Change the complication so it looks differently, which will actually make the app less useful to its users
  3. Remove the complication from the app
  4. Give up, and just keep the improvements in the latest version for myself

Option 1 would be best, although it means waiting another week for a review with an unknown chance of success (probably low because I’ve already appealed)

Option 2 is what I may be forced to do, although it really pains me to make my app worse just to work around Apple’s incompetence

Option 3 would clearly make the app worse, and I know it’s a key feature for more than one user (including myself!)

Option 4 is where we are right now, and is where we’ll be until I find the energy to do something else :(

As you can probably tell, I’m not very happy on where this has ended up.


App Store Issues with Watch Update

I’ve been making some minor updates to Count The Days Left

  • Added an optional badge icon so you can see how many days are left without even opening the app
  • Made the app universal so it works better on the iPad, improved the layout so it works in both in portrait and landscape modes, and can be used in Split View

Neither of these improvements are particularly interesting, but what I thought I’d write about was a very irritating bug in either the App Store or Xcode 7.2 (or some combination of the two).

As you can imagine none of the changes are particularly massive, but uploading an archive to iTunes Connect gave some strange errors:

  1. WatchKit 1.0 - Your previous version used an extension for Apple Watch but your current version doesn’t. Users who haven’t updated their Apple Watch to watchOS 2 or later may lose access to their Apple Watch extension.
  2. Invalid Icon Name - The watch application ‘daysleft.app/Watch/daysleft WatchKit App.app’ contains an invalid icon file name ‘daysleft.app/Watch/daysleft WatchKit App.app/WatchAppIcon44x44@2x.png’. Make sure that icon file names follow the pattern “*@x.png" and they match the required dimensions. Please visit developer.apple.com/watchkit for more information.

In particular the 2nd error is strange, as I’ve just used the standard Xcode Images.xcassets template to set the images. There is a 44x44@2x image required which I’ve definitely set to an 88 pixel square image, but it looks like there is a bug setting this in the archive generation.

Screenshot

I’m definitely not the only person seeing this issues, as there is at least one existing Radar bug been opened on the same topic. I also opened a Radar (23871724) - it seems opening duplicates is the best way of making sure Apple know it’s a common problem - which is now closed as a duplicate of yet another one (23859182) - so hopefully this is being addressed by Apple.

My guess is that this became a problem after I upgraded to Xcode 7.2, but I don’t have the energy to revert back to 7.1 to confirm.

I’m not sure if this will prevent the new version being released, so I’ve submitted it and all being well it’ll be available shortly.


watchOS 2 Complication Update Issue

Unfortunately there was a bug in v2.0.0 of Count The Days Left where the watch complication wasn’t reliably updating itself.

Fortunately the issue was interesting enough to blog about :)

What I believe was the issue - not 100% sure but it appears fixed now - is that a watchOS 2 app only has a limited budget of time where it’s allowed to update itself.

In the getNextRequestedUpdateDateWithHandler function in my complication data source class, I was telling the watch to update once an hour. This seemed a reasonable compromise (without thinking much!) where the watch would update itself once an hour automatically, even if the options for the countdown didn’t change - which forces a complication refresh.

However I believe that once an hour is too frequent. If you read the Apple Documentation closely, it says:

At the end of a scheduled update, ClockKit calls the getNextRequestedUpdateDateWithHandler: method to get the time for the next scheduled update. Specify a date as far into the future as you can manage. Do not ask the system to update your complication within minutes. Instead, provide data to last for many hours or for an entire day. If your budget is exhausted, the next scheduled update does not occur until after your budget is replenished.

Now obviously my count only updates once a day, so I can return in getNextRequestedUpdateDateWithHandler to next update itself at the start of tomorrow, which means it will only automatically update once a day (but should be correct all that day!)

It appears to have worked on my watch overnight, so I’m sending a v2.0.1 to the app store today (Wed 21 Oct 2015). The last version made it past review and into the store in about 2 hours(!), but it’s unlikely to be that quick again.

Update (2015-10-29)

Turns out it was more complicated than I thought :)

Even after the fixes above the complications still intermoittently failed to update overnight. I just think the “automatic updating” is just a bit flaky.

Anyway, I’ve much improved things by putting in an additional call to update watch complication every time the iPhone app, today widget or watch app is access. I also added a background app refresh handler in the iPhone app to call the same update method when ever it is intermittently called.

All of these calls shouldn’t be too frequent - so should have a neglible effect on battery life I hope - and guarantee as much as I can the complication is up to date.

Another version has been submitted to the app store, and hopefully this one will fix the issue.

N.B. All code can be seen on GitHub


Count The Days Left v2.0 Summary

All done! A final few tweaks and v2.0.0 of Count The Days Left has been submitted to the app store for review.

Things I learnt

Developing for the watch is fiddly

watchOS 2 is a pretty big change from the first version, with the extension code now running on the watch. In theory this should help the performance of watch apps - and I believe it does - but some thought needs to be put into to how you manage your data flow between the phone and the watch to optimise this.

I also struggled for a while understanding the best workflow for testing watch apps, using a combination of the XCode simulators and the watch itself, but definitely learnt a lot along the way what works best.

Is Swift ready for prime time?

I really like Swift as a language compare to Objective-C (although now I’m used to the crazy square bracket syntax I don’t mind the latter any more), but I don’t feel as though XCode is quite as reliable when building a Swift project compared to an Objective-C one.

Sometimes the dependency detection on what changed seemed a bit flaky, or the compiler would say a setting is missing from an Info.plist file when it was actually there (and a recompilation “fixed” the issue).

None of the problems are major, and won’t put me off starting a new project using Swift. However I’m hoping things get fixed in later versions of both XCode and Swift.

What next?

Right now I think I’ve reached the end of features I can add to the app, at least until iOS10/watchOS3 come out and offer some new things to play with.

However I’m always open to suggestions, so drop me a line at johnp@bravelocation.com or reach out on Twitter to @yeltzland if you have any thoughts.

v2.0 Articles

N.B. All code can be seen on GitHub


watchOS 2 Complications Complications

So I decided against adding a glance to the app as promised last time, as it doesn’t really add much value over the app itself, and to be honest I found it quicker to go straight to the app rather than try to scroll through my glances.

Anyhoo, I’ve had a load of fun trying to get the complications working, and after more to-ing and fro-ing finally have it working.

This should have been easy, especially as the built in templates for the smaller complications already have the “progress ring” that matches almost exactly what I want.

Apple’s documentation is OK if a little dry, and there are few helpful examples that can be found with a quick search.

The one key point I found was that the XCode project settings where you set the data class to be used for the complications data isn’t quite correct.

What you need to do is set the class in Info.plist to be: $(PRODUCT_MODULE_NAME).ComplicationsDataSource

not:

ComplicationsDataSource

as the target\General\Complications Configuration would suggest.

So I think v2.0.0 is just about done! I’ll need to generate the App Store screen shots and text as usual, and then hopefully it’ll be released in the next couple of weeks.

I’ll probably write a summary post soon too to summarise all these ramblings :)

N.B. All code can be seen on GitHub


Testing a watchOS 2 app directly on the watch

TL;DR

This is a fairly long story with a lot of false trails, so if you just want the best way of testing on the watch I’d skip to the end

The app never seems to start on the watch

In my last post I mentioned that although the app worked fine in the Watch simulator, it was “slow” on the watch - in other words it never seemed to load at all.

I first assumed the problem was that the app initialization was taking too long, so I tried a few things including:

  • Adding in-memory caching to the data model class to (maybe) improve subsequent reading of user settings post initialization
  • Changing the data model to be held in the App/Watch delegate class so it’s only initialized once per app
  • Moving the watch session connection code to run on a background thread so it didn’t block the UI thread loading the initial view controller

All of these changes made a difference in the load time on the simulator, but still no joy running on the watch :(

Pushing a TestFlight app to the Watch

I finally realised I must be missing something, so after doing a bit of research I found out that only signed versions of a Watch app will run on the actual device.

This made a lot of sense, so I followed the further advice of pushing an archived version of the code to the App Store, and then installing it on my phone (then watch) via a TestFlight install.

Now this actually worked, but it took me ages to actually get an acceptable archive working.

The problem was I was trying to reuse the code in both iOS and watchOS using a code library, and I just couldn’t get the archiving to work and sign the various bits of code correctly.

This is crazy complicated (for me at least) and to be honest whenever I’ve used a dynamic library other that through pods I’ve always had issues. Not sure if it’s me or it really is a complicated problem, but it seems the worst part of iOS development compared to most other languages and platforms.

In the end I gave up with the library approach on the watch, and just added the shared code files to the Watch Extension target directly which did the trick.

Solution: Add watch to provisoning profiles

Although the “TestFlight” solution worked, clearly it’s non-optimal as there’s a long iteration time to test any changes on the actual watch.

Some more research found this excellent post by Jared Sinclair on how to solve this problem by adding you watch to your provisoning profiles.

I won’t repeat Jared’s post here, and it’s sort of “obvious once you think about it” (which clearly I didn’t!), but I guess I did learn a lot along the various false trails - which is the purpose of the exercise :)

Next Steps

  • Add a glance view
  • Add watch complications
  • Ship it!

N.B. All code can be seen on GitHub


Synching user settings on watchOS 2

In my last post I mentioned that watchOS 2 doesn’t have access to NSUserSettings, which isn’t entirely correct. The watch can have access to user settings, it’s just it can’t directly synchronise them when they are backed by iCloud.

This means if we change the user settings on the phone we need to push the changes to the watch ourselves.

This isn’t too tricky to do if you follow the instructions on the Apple Developer site about using WCSession to set up a sharing session between the phone app and your watch extension.

As I wanted to continue sharing code between the two apps, I’ve had to add a slightly hacky onWatch property to the settings class so it:

  • Only uses iCloud synchronisation on the phone
  • If a setting is changed on the phone, it sets up a WCSession and uses it to send a Dictionary containing the changes via transferUserInfo()
  • The watch will receive those changes in didReceiveUserInfo() which it can then use to update it’s local settings

There’s a small “code smell” of adding in this onWatch flag just so I can reuse some code in this way, so I may come back and revisit this code later.

According to the docs transferUserInfo() queues any transfers up to send to the watch when a connection is available.

The solution seems to work pretty well - in the watch simulator at least! On the watch itself the app does seem to run rather slow, but TBH that seems a problem with most watchOS apps I’ve used. More investigation needed!

Next steps: Start tidying up the UI in the existing app, and see if we can improve the performance on the actual watch.

N.B. All code can be seen on GitHub


Updating code to watchOS 2

Updating my Count The Days Left app to watchOS 2 is clearly going to be more work than I thought :(

Upgrading to latest version of Swift

After loading the existing project into XCode 7, it prompted me to update the Swift code, and when I accepted did a pretty good job of fixing everything up.

As a learning experience I reverted the changes to fix them up myself. Changes made included:

  • Changing the way string length is calculated e.g. count(self.model.title) => self.model.title.characters.count
  • Using generic Dictionary<String, AnyObject> where previous used NSDictionary
  • Updating NSCalendarUnit values e.g. NSCalendarUnit.CalendarUnitDay to NSCalendarUnit.Day
  • touchesBegan() event handler now has a Set<UITouch> parameter instead of a Set<NSObject> (and a ? on the event)
  • Lots of places I’d used var could be replaced by let - too much C# in the day job I suspect :)

Two versions of the shared library required

The big architecture change in watchOS 2 is that the watch extension code runs on the watch not the phone.

This should make the app much quicker, but brings in a whole raft of problems when migrating the code.

First up was making use of the shared library on code used by both the iOS app and the extension. The version running on the watch needs to be compiled against the watchOS SDK (obviously).

Getting this working stumped me for a while until I found this transition guide on the Apple developer site. See the Sharing Code Between an iOS App and a watchOS App section on how to make a duplicate library using the same files but compiling against the correct SDK.

Can’t share NSUserSettings any more

After solving the above problems, everything built and deployed to the simulator/phone/watch OK, but the watch app didn’t actually work. However a bit more reading of the upgrading code documentation pointed out a fundamental problem.

Because the extension has moved over to the watch, it doesn’t have access to the NSUserSettings objects, even if we’ve set up the App Groups capability correctly.

This means I’ll have to roll my own sharing of data between the app and the extension, which is a bit of a pain, but should be fun to learn.

More on how I get on next time!

N.B. All code can be seen on GitHub


WatchOS Development Phase 2

So I treated myself of an Apple Watch.

I’m enjoying it so far, but despite being heads down in getting the all-new v3.0 of Daily Optimiser out the door, and back contracting in London (earning some money!), I wanted to make some improvements to Count The Days Left now I can actually see it running on an actual watch.

There are several things in the original version that can be improved on or added to. In no particular order:

  • Upgrade to watchOS 2 and latest version of an ever evolving Swift
  • Design! A white background? What was I thinking :(
  • Adding a glance. It’s now pretty obvious this is the natural place for main access to the app (like the Today widget is the most useful part of the main iOS app)
  • Adding a complication so the days left can be seen on the main watch screen

I’m hoping to get all the above done quite quickly, and as before I’ll be blogging here about what I do as well as sharing the code on GitHub

If you missed it and you’re interested, you can see a summary of the previous iteration , which includes links to earlier posts.


App Development using Swift - A Summary

My first app written in Swift has now shipped and with the Apple Watch update now live too I think we can call it done.

So what did I learn?

Swift - good and bad

The Swift language itself is pretty well designed, and a LOT easier on the eye than Objective-C. The syntax is pretty similar to many modern languages and I think I became reasonably productive quite quickly.

The only downside is that most of the code I wrote was generally just interacting with the iOS frameworks, which aren’t particularly Swift-friendly right now. This means you spend a lot of time dealing with nullable pointers, and with all the slightly mysterious ?s, the code loses some of the readability gains.

Hopefully this will get better over time, any maybe this year’s WWDC will see some progress in making the frameworks a little more Swift-friendly? Let’s hope so.

Summary

I enjoyed using Swift, and almost certainly for any new apps starting from scratch I’ll use it.

However I don’t see there is enough - or any - real advantage in porting any existing Objective-C code so any existing apps that I’m working on I think I’ll keep that way.

Anyway, I learnt a lot and I hope you enjoyed following along!

Previous posts in the series

The code for the project is also available on GitHub


Pushing a WatchKit app to the AppStore

Now Count The Days Left is in the App Store, I thought I should push out the next WatchKit enabled version just in time for anyone who’s getting on on the first day.

Issues shipping a WatchKit app

The release process was pretty smooth - well as smooth as any release to the AppStore is - with a few extra steps needed because of the WatchKit support.

1. You need to add a new Watch icon and screenshots

Surprisingly the icon needs to be 1024px square, but I just reused the image I’d made for the main watch. The screenshots were easy enough to produce in the simulator.

iTunes Connect for WatchKit apps

2. No TestFlight support (yet?)

Bit of a pain this one - I suppose this may come later once the watch is out officially? Something to bear in mind if you want to test your app this way and have added WatchKit support.

3. All your version and build numbers must align

Another pain, as I was using a build script to auto-increment the build numbers for the main app - documented here. However there is no “Build Phases” section for the WatchKit App target in XCode, so I had to remove the script and manually set the build numbers to all match.

There are full details on the Apple developer site on preparing your WatchKit app for release.

Next steps

All done I think, just need to write a summary blog post in a day or so.

Previous posts in the series

The code for the project is also available on GitHub


Count The Days Left released

v1.0.0 is finally in the App Store!

It was the usual wait of about 8 days from submission until release, and I still can’t find it from my phone.

However if you really can’t wait, this link should take you there.

Next steps

I’ve released a new version (v1.0.1) including the WatchKit additions I made, hopefully in time for all those lucky people who are getting new Apple Watches.

There were a few things I had to do to ship the extension, and the steps needed requires a separate post.

Previous posts in the series

The code for the project is also available on GitHub


Playing With WatchKit

While v1.0.0 of “Count The Days Left” is waiting for review, I thought I’d have a play with getting a Apple Watch extension written for the app.

Simple is Good

Now as you probably know, the first version of WatchKit is very limited on what you can do in the UI. There are just a few standard controls, no way of writing your own, and any animation can only be done using image sets that are shown one after the other.

However the upside of this is it’s pretty quick to get up and running, and I’ve got something reasonable working after just an hour or so’s work.

Now there are lots of really good starter tutorials out there on getting up and running, so I’m not going to go into too much detail here, but here are a couple of articles I found particularly useful:

The thing that I thought was going to take the most time was generating the collection of images I needed for the animation of the progress circle. Fortunately I found a link to this Radial/Ring/Circle Progress Chart Generator for Apple WatchKit on GitHub which did exactly what I wanted!

Here’s a screenshot from the Watch Simulator with what the app looks like right now:

Count The Days Left on Apple Watch

I haven’t found a way of capturing the animation to show here as the progress circle moves into position, but on the simulator at least it works pretty well.

Next steps

Well I think I’m just about done!

I’ll probably write a summary article wrapping everything up once the app is safely released in the App Store.

Previous posts in the series

The code for the project is also available on GitHub


Waiting For Review

Version 1.0.0 of “Count The Days Left” is now waiting for review in the app store. Hurrah!

As usual it’s a bit of a slog preparing to ship the app, but it’s finally all done, which means hopefully it’ll be available for the public in a week or so.

App Store Video production

I wanted a preview video in the app store to show off the app’s gratuitous animation. This is now easy to capture as the latest versions of MacOS support having an iOS device as a video source for QuickTime.

However, it turns out QuickTime captures my iPhone 6 at nearly 60 frames per second, but teh App Store videos must be 30fps or less.

Luckily I found a nice utility program called Prism Video File Converter Free in the Mac App Store which did a nice job of the conversion, and I could add a short preview of the app.

I made a feeble attempt at adding a sensible description of what’s a pretty simple app, and now we’re all set to go.

Call for Beta Testers

Even though the app should be available in a few days, if you want to get a preview feel free to mail me and I’ll set you up in TestFlight.

Next steps

  • Hopefully a successful app launch
  • Start planning support for the Apple Watch using WatchKit

Previous posts in the series

The code for the project is also available on GitHub


Getting Ready to Ship Swift

We’re getting close to shipping the app I’ve been blogging about, so there’s a few bugs to fix and housekeeping tasks to be done first, to get everything closer to production quality.

Switching back to XCode 6.2

I couldn’t get the deployment tools working in XCode 6.3 beta (not surprising I suppose), so I decided to switch the code back to the recently released XCode 6.2.

This also meant changing the Swift code back to the previous version too which was a bit of a pain, but in reality all this meant was getting rid of the new - but slightly confusing IMHO - casting commands of as? and as!

The only other change was replacing the much improved count(string) function to get the length of a string with the rubbish countElements(string). Surely an extension method on the String class to get the length should be in the language (or have I missed something?)

You can see from the commit on GitHub the changes I made.

Integrating Fabric

I’ve also integrated Twitter’s Fabric framework for tracking bugs. They had a slightly strange installation program that’s somehow watched XCode for builds, which doesn’t seem particularly reliable, but I think it’s now all set up correctly. Hopefully this relatively simple app won’t have any crashes, but good to know I should be able to diagnose them if it does.

Bug fixes

I’ve been using the app over the last week or so, and have made a few more improvements:

  1. Added a timer that fires at midnight each night and refreshes the view, just in case the app is running overnight and needs updating
  2. Picked a new color palette from paletton.com to tweak the color scheme
  3. Improved the layout of the main screen so it works better on larger screens - basically set the main control to have a fixed margin from the edge, and have a 1:1 aspect ratio rather than a fixed width and height. This means it scales better on larger screens as well as all the standard phone screen sizes.
  4. Added a shadow on the main control to get away from a totally flat view. Makes a surprising difference in improving the UI

Screenshots

I used the excellent LaunchKit to take the screen shots I’d take from the emulator and automatically produce the different sizes needed for the App Store. Will definitely use them again as it was efficient and quick.

Here’s what the main screen now looks like on my phone:

Main Screen Screenshot

Next steps

  • Final App Store preparations - basically the copy for the app description needs writing
  • Test the beta version via TestFlight - let me know if you want an invite
  • Start planning support for the Apple Watch using WatchKit

Previous posts in the series

The code for the project is also available on GitHub


Counting Weekdays Between Two Dates

Been slower going now I’m in a contract again - need to get paid!

However I’ve finally got around to fixing the algorithm I was using to calculate the number of weekdays between two dates.

I knew the original one I’d found via a web search was wrong, as I could see the results were wrong when calculating how many days left in my contract. I wrote a failing unit test to capture the issue, and then set about using my brain instead of taking other people’s code for granted.

The algorithm

As ever the code is the most succinct way of describing the solution, but as a basic outline the steps are these:

  1. Adjust the start and end datetimes to be the start of the day
  2. If the start date is a Saturday or Sunday, move it forward to the next Monday (SAdj)
  3. If the end date is a Saturday or Sunday, move it back to the previous Friday (EAdj)
  4. Calculate the days between the adjusted start and end dates (EAdj - SAdj).Days = AdjTotalDays
  5. Calculate the full weeks between the adjusted start and end dates (AdjTotalDays / 7) = AdjWeeks
  6. The tricky bit - Get the day of week (using Apple’s numbering of 1 == Sunday…7 == Saturday) for EAdjDayOfWeek and SAdjDayOfWeek
  7. Calculate EAdjDayOfWeek - SAdjDayOfWeek = DaysDifference
  8. If DaysDifference < 0, then DaysDifference += 5 (this is to adjust how the week wraps around the weekend)
  9. Finally, return (AdjWeeks * 5) + DaysDifference

I think this is correct, and all my unit tests show the model now behaves as I expected, so I think we’re all good!

Next steps

I’m ready to let people start beta-testing the app, but because I’m using a beta version of XCode I can’t use TestFlight and the iTunes Store.

However this might be a good time to check out Twitter’s dev support including Crashlytics and their Beta distribution support.

Previous posts in the series

The code for the project is also available on GitHub


Animating Progress

More progress of sorts, and getting close to having a beta release ready for testing.

Animation in Swift

I wanted the progress to dynamically slide in when the progress bar was shown, and this was done pretty easily using a standard CABasicAnimation on the “strokeEnd” of drawing the line. The code needed to be refactored a little to use layers instead of straight drawing of the line, but again nothing really of interest to show (so looking at the code is clearest if you’re interested)

I tried adding Facebook’s lovely Pop Animation framework, but this was very problematic as it’s an Objective-C library. I nearly got it working before giving up, but will definitely post more on this subject when I try again later.

Other bits and pieces

I also added a swipe left gesture to go from the main screen to the settings, made a simple logo and also added the percentage done to the today widget - I’ve been using the app this week as I’ve started a new contract which has been helpful to improve the interactions.

Next steps

Unfortunately it looks like there is a bug in the “weekdays only” calculations. I have a unit test to prove it, so need to fix this before I’m happy to send out for testing.

Previous posts in the series

The code for the project is also available on GitHub


Swift and Build Odds and Sods

Lots more tweaks of the UI, in particular making a better Settings page.

Settings Page

It’s a pretty straightforward static table view, but there were a few things I learnt/remembered along the way that are worth sharing here.

Selectors in Swift

Installing the app on my iPad exposed a bug I’d introduced in a selector - just shows you can’t always believe everything you read on StackOverflow!

Setting up the handler for incoming notifications, you need to add a colon to the end of the method name in the selector e.g.

NSNotificationCenter.defaultCenter().addObserver(self, selector: "updateKVStoreItems:", name: NSUbiquitousKeyValueStoreDidChangeExternallyNotification, object: store)

Also on the function being selected, you need to annotate the function with @objc so it can correctly interact with the Objective-C library code calling it

Custom data entry for text

I wanted a simple way of entering dates, as I stated in an earlier post simply adding a DatePicker to the page is pretty ugly and takes up a lot of screen.

The solution is to show the dates in a textbox, but then setting the inputView of the text box to be a DatePicker.

// Setup the date pickers as editors for text fields
self.textStart.inputView = self.startDatePicker

Text Date Picker

Obviously you have to take care in calling self.view.endEditing(true) as appropriate when other elements are selected, but it’s a neat solution that works well.

Setting the build version automatically

I can’t remember where I found this originally, but I’ve used it in projects before. Basically I want to set the build number automatically based on the Github revision number, so I can call it in the code.

The trick is to add this script as part of the “Run Script” you can set in a target’s Build Phases

git=`sh /etc/profile; which git`
appBuild=`$git rev-list --all |wc -l`
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $appBuild" "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}"
echo "Updated ${TARGET_BUILD_DIR}/${INFOPLIST_PATH}"

You can then use this to add a version number to your display:

// Add version number
let infoDictionary = NSBundle.mainBundle();
let version = infoDictionary.objectForInfoDictionaryKey("CFBundleShortVersionString") as! String;
let build = infoDictionary.objectForInfoDictionaryKey("CFBundleVersion") as! String;
self.labelVersion.text = String(format: "v%@.%@", version, build);

Having a version number in the settings can be invaluable when trying to debug customer issues.

Next steps

Add some quality and animations to the counter control

Previous posts in the series

The code for the project is also available on GitHub


Adding a Custom Control

I wanted a nice graphical way of showing the progress of the days counted, so I had to make a custom control.

Luckily a couple of days ago I found a great article on how to do almost exactly what I needed.

After a few tweaks from the article code to expose some hard-coded values as properties, it didn’t take long to get something up and running. I’m not going to repeat the article details here, as it’s very clear.

The easiest way of sharing code between the main app and the today widget is to put the shared code in a separate library, which can then be linked to by both targets.

The main view of the app is now much better looking…

Main view

I also wanted to add the control to the today widget, which looks a lot better now too …

Today Widget screenshot

Next steps

Improve the UI of the settings view, and overall navigation between the views

Previous posts in the series

The code for the project is also available on GitHub


Basic UI in Swift

Now we have the data model code ready, we can start building out the UI for the app.

Basic UI

Working in storyboards, there is obviously very little difference doing this with Swift ViewController code rather than Objective-C, especially with such a simple UI.

Storyboard screenshot

As you can hopefully see from the screenshot of the storyboard, there are just 2 views in the app - one to show the number of days left, and a settings view where we can edit the values in the data model.

Later on we’ll come back to this to make the views look a bit more polished, but I just wanted get the app up and running first before tackling some more slightly interesting problems.

A few things learnt

There’s not a lot to say about the Swift code here as it’s pretty simple. However there were a few things that puzzled me a little during development that I thought I’d capture here.

I didn’t know the DatePicker control has a fixed height, which made it very confusing at first as my initial attempts as restricting the height using AutoLayout constraints just didn’t work. There are ways you can change this using frame size manipulation but I wasn’t happy with doing that in my first pass. I’ll revisit the layout of the settings page later.

Also I’d forgotten how to handle hiding the keyboard when the focus goes off a text field (or when the user presses return on the keyboard). As I’m sure you know the secret is to fire a self.view.endEditing(true) in a touchesBegan event handler, and also implement the UITextFieldDelegate and add the endEditing call to a func textFieldShouldReturn(textField: UITextField) -> Bool method as well

Next steps

Add a widget to Today notification screen, which will involve a little refactoring of the code to make common elements shareable

Previous posts in the series

The code for the project is also available on GitHub


A Today Widget in Swift

Making a widget to show on the Today notification screen is pretty straightforward, and as I’d done it before it was pretty quick to do this.

However there are a few steps that must be done correctly for this to work, so it’s probably useful for me to document them here so I remember quicker next time.

Putting shared code in an embedded library

The easiest way of sharing code between the main app and the today widget is to put the shared code in a separate library, which can then be linked to by both targets.

Adding a new target to your project via the “Editor->Add Target…” is the simplest way, and you need to select an “iOS/Framework & Library/Cocoa Touch Framework” template. I tried choosing the static library type, but that only offered me an Objective-C project type which didn’t seem correct even though the data code I’m sharing uses the Foundation code and is non-UI.

After adding the new target, it’s then easy to move the existing files - for me the data model code that’ll be shared in both the app and the widget - into the new target by making sure the files are references in the “Compile Sources” section on the “Build Phases” tab of the target properties (and obviously removing from the original target)

Finally, you’ll need to check the “Link Binary with Libraries” sections for all the targets reference the new library as appropriate, and then the Swift code has the appropriate import daysleftlibrary code to reference the library code

Setting the app group for the user settings

To allow two different targets access to the same user settings, they need to reference the same App Group where the preferences are hold.

App groups in XCode

Once that’s done, you also need to reference the group name as the suiteName parameter in the constructor of your NSDefaults object

Setting the widget title in the Today screen

By default, the title of the widget in the Today screen will take the target name, which for me was the ugly “dayslefttoday”. To be able to override this you can set the “Bundle display name” target property to the required string

Setting the Bundle display name

You can see the results of this stunning widget below:

Today Widget screenshot

Next steps

Undecided yet whether to have a play with the WatchKit, or with some animations in the main app. Stay tuned :)

Previous posts in the series

The code for the project is also available on GitHub


Porting UserSettings code to Swift

Next stage of the app is to store the settings we previously added to both the local user settings and to iCloud for syncing across multiple devices.

Luckily I had some Objective-C code I could repurpose for most of the logic, but porting it was a useful exercise in getting used to the slightly obtuse casting syntax necessary in Swift when interacting with the frameworks.

Setting up iCloud preferences

To enable storing key-value pairs for the app in iCloud, it’s as simple as going to the Capabilities section of your project settings, and:

  1. Turn on the iCloud capabilities
  2. Make sure the “Key-value storage” checkbox is selected

Code to get and set preferences

The code - available on GitHub for viewing - is reasonably straightforward port of some common code I’ve used before.

I’ve refactored the main settings code into a BLUserSettings.swift class I should be able to reuse in other projects. The existing DaysLeftModel class now inherits from this base class, and the getters and setters have been changed to call the appropriate read/write methods in the base class.

The getters will read from the local user settings, so they’ll be available even if the device is offline. The setters will write to both the local store, and the cloud store, and the base class also handles notifications if the settings have been changed on a remote device, and writes them locally as appropriate.

Having a bunch of unit tests as always helped to test my refactoring of the model class worked fine.

Next steps

I think we’re now ready to start on the UI.

Previous posts in the series

The code for the project is also available on GitHub


Baby Steps with Swift

As per my previous posts, I’m developing an iOS app “in the open” using Swift as a learning experiment. It’s going to be an app that counts down the days to a future date.

Data Model design

I thought a good way of getting started would be to work on the data model code. There would be more pure Swift code to write to get up to speed on the syntax, plus I’d get the chance to write some unit tests too.

The data model design is pretty straightforward; I want to have the following properties to hold the settings data:

  • start: NSDate
  • end: NSDate
  • title: String
  • weekdaysOnly: Bool

Then there are three different access properties/methods to calculate various day lengths:

  • DaysLength: Int - the number of inclusive days between the start and the end
  • DaysGone(currentDate: NSDate) -> Int - the number of days from the start to the current date
  • DaysLeft(currentDate: NSDate) -> Int - the number of days to the end to the current date

Swift strangeness

Writing a simple class to implement this logic was pretty simple even in a new language, although a few things were a little strange at first in Swift.

Semi-colons at the end of the line are optional in Swift, and a few references I found seemed to say best practice is not to add them, although muscle memory from Objective-C and C# made this hard to do.

Also integrating into the IOS Foundation classes was a little strange in places especially the use of optional values. For example, note the ! at the end of this line

model.start = NSCalendar.autoupdatingCurrentCalendar().dateFromComponents(startComponents)!

My model.start is of type NSDate i.e. can’t be null, whereas dateFromComponents() can return a null value, so the ! forces this to actually return a value (I think!). Not the most intuitive, but thankfully the XCode editor prompted me to add the exclamation point.

The other problem I had initially was being able to reference the DaysLeftModel class from my unit test code. I couldn’t figure out anyway of importing the model code, before this very helpful blog post by Andrew Bancroft pointed out the way of configuring the build settings to automatically create a module.

Date calculations

For the date logic of calculating the difference between two dates ignoring weekends was a little tricky, but as usual the Internet was my friend and with the help of TDD and the algorithm outlined in this article by Alec Pojidaev I managed to get it working correctly.

The code

So I’m happy to be up and running in Swift, and the code is up at GitHub if you’re interested.

Next steps

I think I’ll next tackle storing these settings in a local datastore, as well as synching them with the cloud to share across devices.

Previous posts in the series

The code for the project is also available on GitHub


Plan for DaysLeft app

I’m currently in-between contracts, so as promised last week I’m going to try developing a new app in Swift "in the open" and see how we get on.

My idea is to write a simple app that basically counts down how many days left until a certain date. This was inspired by the fact that in my last contract I used a spreadsheet to count down how much I had left to go (it wasn’t that bad really!)

I wanted something simple enough that could be completed in a few days - even though I know very little Swift before starting - and could be extended into an Apple Watch app.

Now there are hundreds of similar apps out there in the app store already, so this isn’t going to be groundbreaking in any way, but hopefully when it’s done it’ll find a small audience.

One-Page Plan

Before starting coding, obviously I want to do a little planning.

I’m very much a believer in doing just enough planning to get started along the right path, and if I had a test team enough information for them to understand what the app should do (but no more).

I’ve finally broken into my Evernote Moleskin notebook to sketch out a mini-design for the main app, and used the Evernote Scannable app to snap a picture:

DaysLeft Plan

Beautiful or what?

More usefully, I’m tracking the actual tasks in a Trello board which you should be able to see if you’re interested.

The initial tasks on the backlog - in probable order of development - are:

  • Code to handle settings in iCloud
  • Settings view to handle input etc.
  • Simple main page to show days left
  • Unit tests for calculations
  • Daily notifications
  • Today screen widget
  • Watch extension
  • Main page animations

Next steps

Start coding!