MVVM + Coordinator = 🍰

I've been using the god-mix of the MVVM pattern mixed with the Coordinator pattern to build Tacks - and I'm a huge fan of the approach.

Prior to adopting this, when I was using only MVVM, there was always the question of who was responsible for navigating between the screens - who makes the overarching decisions regarding what to do next? The implementation of which would float awkwardly somewhere between the ViewController (VC) having the presentation of the next screen hard-coded (which hurt reusability), or the ViewModel (VM) somehow nudging the VC and whispering "now go to the success screen" or whatever into it's ear. This really polluted the concept of "single responsibility" for both of these components.

It was also never super clear who should create the VM to be injected in to the VC either. The way I had been doing it, the ViewModel of the previous screen would create and configure a "Child View Model" to be injected into the ViewController that was being presented.. which was a bit messy, and unfortunately coupled the two screens together.

Enter stage: Coordinator 🎺

What the Coordinator pattern adds to this mix is the role of an overseeing "Coordinator" object (duh), responsible for a particular flow of your app, e.g. The Signup Flow.

It owns a canvas (a NavigationController, for example) onto which it can present ViewControllers as it wishes and, like a puppet master, sits high and mighty above the VC+VM layer pushing and pulling and popping screens into place, and responding to the output to decide what to do next. It is therefore the Coordinator's job to create both the VC and the VM, and to configure them as necessary.

Peeling away this responsibility from both the VC and the ViewModel really helps towards reaching the aims of the "Single Responsibility" principle.

In my opinion, the key benefits of MVVM boil down to the following:
- Separating the view model from the user interface makes it easier to test presentation logic.
- Separating the view controller from the presentation logic makes it easier to test the user interface.
— Ash Furrow, "MVVM in Swift"

So, in terms of what the Coordinator pattern adds to this, I'd say:

  • Separating the VM and the VC from the responsiblity of managing navigation makes their actual roles in the architecture clearer and more specific. The implementation becomes dumber and reusability improves. Awareness of flow between screens (i.e. how you got to this screen and where to go next) is completly delegated upwards to the Coordinator - making everything simpler.

--

One last thing to add is that if you allow the VC to communicate with Blah VM only through a BlahViewModelType protocol, you are then free to inject the VC with different implementations of the BlahViewModelType for different purposes, making the VC still further reusable. For example, the MapViewController in Tacks is currently used in three different situations (once full-screen and twice as a child VC on other screens), simply by changing the underlying ViewModel to adjust what is shown.

Tacks 2.0 now in beta

Super happy to announce that Tacks is getting close to public release - this weekend I've kicked off the beta program for those that signed up. If you like, you can try it out before it hits the app store: https://betas.to/fJ3Dq3pz.

So what is Tacks?

Tacks is your private list of places you've discovered and which you want to come back to: great cafes, pubs, parks, sunbathing spots.. β˜€οΈ you get the idea.  You can very quickly drop a pin where you stand, and later retrace your steps back to that spot.  

It's for bookmarking places around you, basically.

portrait2.png

The aim is to make a really use simple but useful tool. In the process, I'll have an app of my own, set aside from my contracting work, with which I can try out cutting edge Swift development techniques.

For example, this project is absolutely full of Functional Reactive programming (I used ReactiveKit), which I want to now blog with some example code ASAP, because it's really cool. I also used the MVVM+Coordinator pattern with great success, I want to blog about that too. There's a bunch more to write about too: the fastlane continuous delivery pipeline for testing, building and shipping builds automatically; extensions made to ReactiveKit

There's some bespoke frameworks which I've developed for the app, which I want to now document and develop as open-source projects in their own right:

ReactiveKitSwappableDatasource (this needs a better name) - a wrapper around a generic collection which allows the underlying dataset to be swapped out on-the-fly, with changeset notifications. e.g. swap a Realm `result` for a plain array of the same type, and it'll compare the differences. Really useful for binding the map to the tableView.

SwipeAndSnapCell - I need to turn this into a cocoa-pod. This is the library I made for swiping  tableView cells, with an iOS10 mail-style "snap".

But first, beta 2, beta 3.. and release πŸš€.

Finding remote freelance work: Toptal?

I'm trying to set myself up as a 100% remote developer, which - as someone who's traveled around a lot in the last few years, - is in some ways very easy (I'm already very mobile, I'm disciplined about working on my own), but in other ways is quite hard (I don't have an established network of existing remote-okay clients who I can plunder for ongoing work). My clients in Amsterdam have been great, but they've had the expectations of hiring a contractor, rather than a freelancer - that is to say they expected 9-5pm working from the office - of course fine if you live close-by, but not so good if you want to work flexibly and remotely.

As a result, I'm putting some work into getting listed as a Toptal developer, though it's quite tricky - you have to complete a challenging timed algorithm test before you take the serious interview. I attempted it a few years ago, completely unprepared for how hard it was, and totally failed (bummer). I'm going to retake it (they let you resit it after 6 months), and this time I'll be ready πŸ’ͺ🏻.

So, I've been practising the lessons on the Codality site (the programmer-testing website that Toptal uses to pre-screen candidates) as a sort of warm up. Though I feel this style of programming challenge doesn't necessarily correlate with someone's ability to build a good and stable iPhone app (it emphasises abstract problem solving), probably they're skills worth honing anyway. And it's pretty fun - like being set coursework back at Uni again.

Codality Lesson solutions: I'm posting on Github my solutions so far.

Tacks: Design: Conjuring a Style-Guide

Or: how to get started designing when you're a developer.

I recently [investigated, a, bunch, of, prototyping, tools] and, man were they all super involved. Great tools, but personally too much. What I was looking for was something akin to "Interface Builder on steroids" - some app with more design tools available for composing the UI (blur, border-radius, vector drawing etc), without dropping down to code, and yet still dragging-and-dropping live iOS native components.

Background

My strategy with Tacks thus far (version 1.x) has been "build the app, get the base functionality working, use all-native components, ship it, then circle back later to address the UI". Not ideal, but I had I not done it this way, the momentum required to build the functionality (in my spare time, between full-time office hours as well as travelling), would have evaporated away long before the app ever saw the light of day. Particularly so given I was building Tacks fully in the Functional Reactive paradigm using ReactiveKit, increasing the complexity (and also the awesomeness) quite a bit.

Solid Red colour scheme πŸ˜‚

Solid Red colour scheme πŸ˜‚

Now that the basic version is now in the App Store - and v2 is really gathering speed - it's become time to apply a decent design. The problem is, I'm no designer.

This guide is mostly aimed at developers who are working on their own apps. Here are some tips for getting started, based on what I did.

N.B. I still plan to stump up some cash to hire a freelance designer further down the line, but for now (whilst I'm still working on core functionality), I just want to keep following my vision for how it should look and work, and see how far I get.

--

v1.0. Well, it was a start..

v1.0. Well, it was a start..

Tacks UI: Version 2.0

The most daunting aspect of attempting UI design is establishing the overall "Look and Feel" of the app. It's quite a scary undertaking.

I suppose I did give up with the UI design of Tacks v1 - as you can see to the right, I arbitrarily chose a not-generally-respected "Solid Primary Red" colour scheme and just shipped it like that.

But now I needed to work out what my screens should look like for v2. They needed still to be native (a lone developer likes an easy life), but slick enough to be a recognisable iOS10 app, not easily mistaken for an iOS5-era app.

I came across this post at ThoughtBot advising designers to prototype directly in Interface Builder, which I initially disregarded but it gave me pause. Interface Builder? Hmm, maybe that could actually work.

Plan of attack

Colours

The first step is to choose a color scheme. There are tonnes of tools online to assist you with this: my favourite is ColourCode, but Coolors is also great. Pick a few colours, and then choose some different shades within that set to use for emphasis, selected-states, etc.

These are the colours that Apple use in iOS (presumably since the iOS7 flat-design refresh)

These are the colours that Apple use in iOS (presumably since the iOS7 flat-design refresh)

Side-note: I'm pretty excited for this:

Style Guide

Next, create for yourself a style guide. This will be your reference point when you're developing your app, and for all decisions about "what should this bit look like", you can relax and refer back to this document that you made for yourself at the start.

Our document will be a simple Storyboard, created in a separate "TacksStyleGuide" project.

Protip: even if you haven't ported your main project to Xcode 8 yet, the new beta does have a more powerful Interface Builder with extra (live) UI features such as blur effects, vibrancy etc, as well as editing at any zoom level. So, perfect for simply creating a Style Guide at least.

Open a new Storyboard StyleGuide.storyboard, add a new ViewController and just go to town. Create every control that you will need in your app, samples of text in the fonts you will use, buttons in different states, icons, etc. Just keep tweaking until it looks good. If you get to a certain point on the first attempt and decide (like I did) that you're heading in the wrong direction, duplicate the ViewController and start again - you can then compare your attempts later. Likewise, experiment using different colour swatches. After you've created a few of these, get some feedback from people you respect.

An early version of mine. When I asked around, the righthand colour scheme was much more popular.Β It's handy to create a colour swatch in Interface Builder as a reference point for each attempt - it's just a short View Controller with a horizontal UIStackView and a bunch of coloured UIViews.

An early version of mine. When I asked around, the righthand colour scheme was much more popular. It's handy to create a colour swatch in Interface Builder as a reference point for each attempt - it's just a short View Controller with a horizontal UIStackView and a bunch of coloured UIViews.

Doing it in this abstract way takes the pressure off. You're not even going to use this storyboard in the app, so it allows you to think about the app more generally rather obsessing specifically about one screen.

Preview as any simulated device

Preview as any simulated device

You can also preview any effects live on a simulated device in Interface Builder using the Preview Assistant Editor. Just add a device (by default it shows Localizations, but we want live effects).

You should also run this Style Guide app on a device to preview how it looks - it can be quite surprising the difference between how you think it looks on a big screen and the reality on a small one (especially in terms of font sizes).

Now go ahead and use this design language to sketch out some components which will appear in the app. For Tacks, this will be TableView cells showing locations:

Still a rough attempt, but helping us form an idea of how the real app will look.

Still a rough attempt, but helping us form an idea of how the real app will look.

Great. So, we have a fairly precise idea of how we want the app to look. But now we should somehow automate the process of styling all the components to look the way we want.

I believe that, beyond the most basic app, Interface Builder should be used for mostly setting up AutoLayout constraints and adaptive layout behaviours, rather than minutely pinning down exact fonts and colours.

Automated styling

I believe that, beyond the most basic app, Interface Builder should be used for mostly setting up AutoLayout constraints and adaptive layout behaviours, rather than minutely pinning down exact fonts and colours. The reason being the tedium of having to manually update all your XIBs or Storyboards later if you change your mind.

The aim is really to transfer all the UI decisions you made in Interface Builder into code, and then to use that to style a plain version of your StyleGuide view controller. If you can do this, the theming code you created can be used to automate the styling of all standard controls throughout your app.

Use UIAppearance and tinting as a broad tool, and create custom extensions on UIKit controls for more precise control (UIAppearance only gets you so far).

You should also create some kind of Theme protocol for your project. This will define the typesetting, groups of colours etc, and will be passed (via dependancy injection) to your ViewControllers to allow them to style themselves.

Here's what I came up with:

Here's where I'm at after applying my new style.Β It's not perfect (or finished) yet, but is quite a leap forward compared to what I had before. Tacks v2 coming soon.. πŸ‹

Here's where I'm at after applying my new style. It's not perfect (or finished) yet, but is quite a leap forward compared to what I had before. Tacks v2 coming soon.. πŸ‹

Further

You could take this one step further and implement any @IBDesignable controls in this separate workspace too. I've basically been treating it like a playground for UI design, so this would be the next logical step.

I definitely recommend using a tool like Reveal.app to customize controls on-the-fly.

Swift Basics: reduce()

By the way, this post is also available as an interactive Swift Playground. πŸ€“

The reduce function is super useful for when you need to compute (or reduce 😏) a set of values down to a single value.

Let's take a look at a simple example. Say we wish to sum an array of numbers to find the total. Without the reduce function, we might use a foreach loop:

let valuesToReduce: [Int] = [1,2,3,4]
var total: Int = 0

valuesToReduce.forEach { value in
    total += value
}

total // total: 10

However, in Swift we try to avoid mutability.

Here is the same calculation written using reduce. Take a look then we'll break it down:

// use `reduce` to sum each Int in an array, resulting an Int:
let total = valuesToReduce.reduce(0) {
    (accumulation: Int, nextValue: Int) -> Int in
    return accumulation + nextValue
}

total // 10

or written more simply as:

let total = valuesToReduce.reduce(0) { $0 + $1}
total // 10

Note that the closure we to reduce is called once for every value of the array.

The zero that we pass in as a parameter is called the accumulator, that is: the starting value upon which successive calls of reduce function will be applied, effectively accumulating our final result. Actually, given that we're using value types and 0 is immutable, we will not be mutating the zero - we're really passing the return value from the first call (i.e. 0 + 1 = 1 - a new value) back in as the starting value (accumulator) of the next call.

We will see at the end that we can also use a mutable object as the accumulator and literally build up our object with each successive pass - which is sometimes useful for working with Cocoa.

Creating An Array from an Array:

The output of reduce can really be anything - even another Array. As a second example, let's use reduce to create a handy deduplication function which we can add as an extension on Array type.

The first thing to decide is what our starting value for this shall be. Our algorithm will be as follows: "start with an empty array and append each item, so long as that item isn't already present in the array". By this logic we shall finish with an array of distinct unique values.

Thus, we should start with an empty array of type <Element> (the Generic placeholder for the type of value the array can hold): [Element]():

extension Array where Element: Equatable{
    func deduplicate() -> [Element]{
        return reduce([Element]()) { (accumulation: [Element], find: Element) -> [Element] in
            guard accumulation.indexOf(find) == nil else {return accumulation}
            return accumulation + [find]
        }
    }
}

let result = ["Amsterdam", "Berlin", "Paris", "Amsterdam"].deduplicate() // -> ["Amsterdam", "Berlin", "Paris"]

Whoa whoa, slow down:

So:

extension Array where Element: Equatable - we should constrain this extension to be available only when the Array holds values that are equatable. Otherwise, how could we identify duplicates?

func deduplicate() -> [Element]{ - we're returning an Array of the elements of the same type that the starting array holds.

reduce([Element]()) { (accumulation: [Element], find: Element) -> [Element] in - [Element]() is what we start with - an empty array. This is the Accumulator that we'll be using. The signature of the closure we're passing to reduce has the accumulation that we're building up accumulation: [Element], and find: Element, the current element that we want to find.

guard accumulation.indexOf(find) == nil else {return accumulation} - if the element we wish to find is already in the accumulation, then exit early from this iteration, returning an unchanged accumulation value. This is the escense of deduplication.

return accumulation + [find] - otherwise, return the accumulation with find appended.

In the next example, we'll show that reduce can also be called on a Dictionary type, and that the accumulator can also be mutable if need-be:

Using a Mutable accumulator instead:

Say we want to take a Dictionary of type [String : NSURL], that is, a mapping of Town Name to Map URL, and turn it into an NSAttributedString of tappable (once added to a UILabel) linked text.

i.e. this:

let placeURLPairs: [String : NSURL] = [
    "Amsterdam" : NSURL(string: "https://www.google.nl/maps/place/Amsterdam/")!,
    "Newcastle" : NSURL(string: "https://www.google.nl/maps/place/Newcastle/")!,
    "Manchester" : NSURL(string: "https://www.google.nl/maps/place/Manchester/")!
]

to this:

We can, naturally, use a reduce function to acheive this. However, the API for building up NSAttributedStrings, is quite suited to using an NSMutableAttributedString and applying successive attributes and String values on it.

It's easy to tweak our reduce function to, instead of returning a new value each time, instead return a mutated version of the passed in accumulator, so this same object will be passed into each iteration and then will be the result by the end:

func attributedString(places placeURLPairs: [String: NSURL]) -> NSAttributedString{

    return placeURLPairs.reduce(NSMutableAttributedString()) {
        (accumulator: NSMutableAttributedString, placeURLPairs: (String, NSURL)) -> NSMutableAttributedString in

        // unpack the name and the URL:
        let (placeName, url) = placeURLPairs

        // Create the local attributed String which we'll append
        let localAttributedString = NSMutableAttributedString(string: placeName + " ")

        // Add a link to this name
        localAttributedString.addAttribute(
            NSLinkAttributeName, value: url, range: NSRange(location: 0, length: placeName.characters.count)
        )

        // Add this attributed string onto the mutable Accumulator
        accumulator.appendAttributedString(localAttributedString)

        // Pass the accumulator back out again
        return accumulator
    }
}


let placeURLPairs: [String : NSURL] = [
    "Amsterdam" : NSURL(string: "https://www.google.nl/maps/place/Amsterdam/")!,
    "Newcastle" : NSURL(string: "https://www.google.nl/maps/place/Newcastle/")!,
    "Manchester" : NSURL(string: "https://www.google.nl/maps/place/Manchester/")!
]

let attributedLinkedTownsString = attributedString(places: placeURLPairs)

let label = UILabel(frame: CGRect(x: 0, y: 0, width: 1000, height: 200))
label.attributedText = attributedLinkedTownsString

Hopefully this was useful, do let me know in the comments if there's any feedback or comments.

By the way, this post is also available as an interactive Swift Playground. πŸ€“

Fixing Xcode CLI builds with broken plugin warnings

I'm a big fan of Carthage, but one issue that had been plaguing me for months was the command line warning messages about my Xcode plugnis not being "compatible".

It rather clutters up the Terminal.

It rather clutters up the Terminal.

PluginLoading: Required plug-in compatibility UUID ACA8656B-FEA8-4B6D-8E4A-93F4C95C362C for plug-in at path '~/Library/Application Support/Developer/Shared/Xcode/Plug-ins/Xcode_beginning_of_line.xcplugin' not present in DVTPlugInCompatibilityUUIDs

etc.

This post gives some good relief - you just pipe a script straight from the 'net straight to sh (πŸ™ƒ) - , allowing Xcode to now recognise all my plugins properly (which were actually working in the Xcode app, but apparently not at the command line) but it revealed that one plugin was broken, the excellent FuzzyAutocomplete:

WARNING: Failed to load plugin at path: "/Users/ian/Library/Application Support/Developer/Shared/Xcode/Plug-ins/FuzzyAutocomplete.xcplugin", skipping. Error: Error Domain=NSCocoaErrorDomain Code=3588 "dlopen(/Users/ian/Library/Application Support/Developer/Shared/Xcode/Plug-ins/FuzzyAutocomplete.xcplugin/Contents/MacOS/FuzzyAutocomplete, 265): Symbol not found: OBJC> CLASS_> $_DVTTextCompletionInlinePreviewController

I guess I hadn't noticed it was broken, so for now I'll just remove it.

Much better!

Much better!

Notes on ReactiveCocoa 3.0 RC

I'll be honest - I did have real problems getting back to grips with ReactiveCocoa 3.0 since their API overhaul (despite being reasonably familiar with v2 - I even gave a talk on it). I'm getting there now (tacks.cc is written extensively with ReactiveCocoa 3.0 RC), and I'll try to update this post with tidbits from what I've learned because, to-date - even though the RAC codebase is well documented, function to function - there's not enough examples out there for how you actually use this stuff as a whole. Most of the example code that exists is still in Objective-C and generally relates to previous versions of RAC. There are some great blog posts (linked at the bottom), which really helped me figure it out.

Creating a signal

We can create a "pipe" which returns a Tuple pair: the Signal itself, and an 'observer' which we can use to manually send events, - events which pop out of the created signal. They go together.

let (self.locationSignal, self.locationObserver) = Signal<CLLocation, NoError>.pipe()

Signal of empty Events:

If you want a Signal that sends empty Next events, create your signal like so: Signal<Void, NoError>, and just send it Voids: .Next(Void)

You don't always need a real Error type

Signals rarely fail, so it's usually easier just to model them using NoError.

let locationSignal: Signal<CLLocation, NoError>

Using next: to start a new signal after completion - this is gone

In RAC 2, we could use next: to start a new signal once another completes. We don't this anymore - instead we concatenate signals, for example: localFetchProducer |> concat(networkFetchProducer)

Create a SignalProducer from a value

let individualComicProducer = SignalProducer<Comic, NSError>(values:comics)

Resources:

Swift 2.0 - ReactiveCocoa API changes

|> -> .

Aside from converting all usages of |> to simply . ( - much better! we now have code completion! πŸŽ‰), a few other notable things tripped me up when switching to the Swift 2.0 api:

.Catch

catch is now a reserved word in Swift 2.0, so you should simply replace all usages with flatMapErrors - it's the same.

.Start

Secondly, the compiler now seems to have problems identifying which default parameter it should use when you pass a closure to start:. Previously it was common to use the following shorthand:

producer.start { value in ... }`

Where we really meant was:

producer.start(next: {value in ...})

The method signature of start: is really:

start(error error: (E -> ())? = nil, completed: (() -> ())? = nil, interrupted: (() -> ())? = nil, next: (T -> ())? = nil) -> Disposable

The Swift 2.0 compiler (Xcode 7 b6, at least) now makes a different decision about what we're trying to do. Due to the fact that we're passing a single block parameter, it now seems to assume that we want to call the start(sink: Event<T, E>.Sink) method instead. This is our clue that something's not right, as we start seeing that our blocks are being passed variables of type Event<YourType, NoError> rather than the expected type.

The solution is easy: either just be clearer about what you're calling by reinstating the next: parameter name:

producer.start(next: {value in ...})`

.. or provide more type information in your closure, to help the poor compiler out:

producer.start { (displayableAnnotations: YourType) in ... }

.Put

We no longer use .put(x) to set the value on a MutableProperty type - .value is now settable, so we just get and set .value directly. This is probably good, though I liked the separation before - it made it more obvious that MutableProperty also dealt in events. But like I say, it's probably simpler now.

Converting a RAC 3.0 project from Swift 1.2 to Swift 2.0

I've been loving ReactiveCocoa 3.0 (now that I've finally grok'd it), and today I was able to switch to the swift2 branch to start updating Tacks's Swift 1.2 code for iOS9.0.

Aside from converting all usages of '|>' to simply '.' instead ( which is much better! we now have code completion! πŸŽ‰), a few things tripped me up when switching to the Swift 2.0 api.

.Catch()

Firstly, catch is now a reserved word in Swift 2.0, so you should simply replace all usages with flatMapErrors - it's the same.

.Start()

edit: as of Sept 7th, convenience methods have been added to get around this, i.e. startWithNext, startWithCompleted, startWithError, as well as for observing Signals: observeNext, etc.

Secondly, the compiler now seems to have problems identifying which default parameter it should use when you pass a closure to start:. The method signature of start: is really:

start(error error: (E -> ())? = nil, completed: (() -> ())? = nil, interrupted: (() -> ())? = nil, next: (T -> ())? = nil) -> Disposable

and previously it was common to use the following shorthand:

producer.start { value in ... }`

Which would really mean (I assume because next was the last parameter?):

producer.start(next: {value in ...})

The Swift 2.0 compiler (Xcode 7 b6, at least) makes a different decision about what we're trying to do. Due to the fact that we're passing a single block parameter, it now assumes that we want to call the start(sink: Event<T, E>.Sink) method instead. This is our clue that something's not right, as we start seeing that our blocks are being passed variables of type Event<YourType, NoError> rather than the expected type.

The solution is easy: either just be clearer about what you're calling by reinstating the next: parameter name:

producer.start(next: {value in ...})`

.. or provide more type information in your closure, to help the poor compiler out:

producer.start { (displayableAnnotations: YourType) in ... }

.Put()

We no longer use .put(x) to set the value on a MutableProperty type - .value is now settable, so we just get and set .value directly. This is probably good, though I liked the separation before - it made it more obvious that MutableProperty also dealt in events. But like I say, it's probably simpler now.

Edit: Extra!

Don't forget to remove the Box dependancy as well, because it's no longer needed with Swift 2.0

Developing Tacks in the open

I have GitHub repo and am talking to myself publicly via GitHub issues, the primary purpose is an exercise in what an "ideal project" for me would feel like (when I'm running the show), as well as being able to demonstrate what my work style (and coding prowess πŸ˜›) is like to anyone and everyone who might be interested (I am a freelance developer, after all). Perhaps someone else might want to join the project too.

Swift learning: Integrating ReactiveCocoa into my canonical Swift app

Ok so I got this far without too many issues, so now to go back to my old favourite (or should that be nemesis?) ReactiveCocoa.

I abortively tried to begin learning Swift 2.0 with ReactiveCocoa 3.beta8 together from the get-go (because if it worked, that would be awesome right?): it didn't work because my Swift experience was too patchy, ReactiveCocoa 3 wasn't even finished and, particularly, wasn't ported to Swift 2 yet. (also I was still trying to get used to Xcode after three happy years using AppCode - which unfortunately is still lacking mature Swift support).

Now that the tears of frustration have dried, this time I'll go back somewhat less ambitiously (retreating to Swift 1.2 for my own sanity) and try ReactiveCocoa 3 again, it now being at RC1.

I've developed my ListViewController already with a ViewModel pattern, using callbacks (didChangeContent, didChangeSection etc) to notify the VC of FetchedResultsController changes. This is a perfect point to start and using Signals (or are they called SignalProducers now..?) instead.

Swift learning: writing a POC canonical Swift app

I'm taking some time off to rearrange my 4+ years of Obj-C knowledge into a Swift-shaped skillset instead. Retooling. There's some other things I want to try too (CloudKit, rspec-style testing with Quick), so this is a good chance to check them out.

Before I take on my next project, I want to have built a canonical POC Swift app which contains many of the usual features of an app and utilises the following implementation features:

  • showing basic data (e.g. a List) in a TableView
  • data is persisted in Core Data
  • data is shown with a FetchedResultsController
  • data is editable
  • UITableViewCell containing a textField
  • MVVM used

  • Unit tests written with Quick & Nimble

  • Convert to Swift 2.0

Once it's converted to Swift 2, then:

  • Xcode 7 User Interface tests written (Swift 2)

The app will be my "best practise" reference going forward, and should basically stay up to date with my own experience.

ReactiveCocoa 3.0 alpha 1

I had some troubles even installing this build (Swift 1.2).

Firstly, the version of LlamaKit that cocoapods installed wasn't compatible with Swift 1.2 (which RAC3.0 is currently targetted at).

I tried the manual install next, but it seems like there's a step missing. If you get some issues like "No such module Result" or "No such module Box", the solution is here - you have to add more than just ReactiveCocoa.xcodeproj. I filed an issue and the Readme is updated to explain this now.

Taking a month off

Last week I was contracting on a great project at Philips. I'd been there since December, and before that I was working on something else, and before that something else.

Time was passing by, and part-time projects were piling up, gathering dust. This last year I'd really dug into ReactiveCocoa, but as a consequence I hadn't really learned Swift yet, and I hadn't been making any open-source contributions for god-knows how long. My portfolio site needs updating, my side-project Tacks.io app lies long since forgotten. I've been living in the Netherlands for 18 months, and hadn't started a Dutch class yet - though I'm pretty hot on Duolingo - challenge me ;)

Contracting is really great, but at the end of the day you're tired, and by the end of a long week coding 8 hours at a desk in a skyscrapper, you just want to relax. I've known for a long time that I work better during the afternoon & evening, and if I can do some decent exercise in the morning then even better.

A few months ago I opted not to renew my rolling three-month contract - WWDC was coming up and I wanted to make a huge gesture to myself, to give myself some time to actually attempt the things I 'never had time' to do. Watch the WWDC videos the week they come out! Write some example apps based on the new stuff! Read through my 120+ Pocket'd programming articles. Finish Design For Hackers. Release my long-time-in-the-making-and-still-objc pet project app Tacks.cc. Working towards being an 'indie' developer with recurring income streams.

Keeping myself a strong and skilled developer involves investing in myself. So now I've got a big block of four weeks 'self self-employed' time. Amazing.

(I've started my Dutch class, too)

Airserver for WWDC

For some strange reason, Apple has so far only released the videos of their Tech Talks in the WWDC app (and on the Apple TV - which I don't have). What if you want to watch them from the comfort of your sofa? Your hands are occupied already rightπŸ•πŸΊ?

Presumably they'll be on the website sooner rather than later, but in the meantime you can easily stream the content to your Mac using the excellent third-party AirServer (conveniently free for seven days). Once it's running, play the WWDC app video on your phone and, via the magic of AirPlay, they'll show on your laptop screen. If you can plug that into the TV, all the better.

Pro-tip: if you use the Share Sheet in AirServer, you even get the direct URL of the talk and can use it directly, dispensing with AirPlay completely.

Introducing Tacks

There's an app that I've been working on in my spare time, which I've actually been using personally for several months, but which I've not managed to pat together into an App store release.

It's a simple app based on something I needed each time I found myself in a new city when I was travelling: when you arrive, you constantly see lots of places you'd like to return to, and it would be super handy if you could just drop a pin there, add a short title and thus remember it for later. After a while, you'll see a map studded with interesting places that you yourself have added, and it's simple to find your way back later on. When you go to the next city, you start a new map, etc.

Inspired by Sam Soffes talking passionately about developing Cheddar on the Founders Talk podcast, I'm going to open-source this app and blog about its development too.

Mail.app fix for Fastmail SMTP in Mavericks

I've been having intermittent issues with Fastmail's SMTP service in Mavericks, where Mail.app will sometimes repeatedly reject the correct password (and thus refuse to send mail).

The fix is to force it to use port 587 for SMTP (it claims it'll try 25, 465 and 587 by default, but this doesn't seem to be reliable):

Preferences -> Accounts -> Fastmail -> Account Information -> Outgoing Mail Server -> Edit SMTP Server List -> Advanced -> Use custom port: 587

iOS8 beta7 NSNumberFormatter bug

I just submitted this bug to Radar, hopefully it's fixed before the imminent RC:

NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
numberFormatter.numberStyle = NSNumberFormatterCurrencyStyle;
numberFormatter.minimumSignificantDigits = 2;
numberFormatter.maximumSignificantDigits = 2;

// on iOS7 this outputs "$123.12"
// but on iOS8 b7 this just outputs "$123"
NSLog(@"%@", [numberFormatter stringFromNumber:@(123.12)]);

I'll have to implement it manually for now, it's fairly nasty:

// bug in iOS8, see here: http://www.iandundas.co.uk/blog/2014/09/04/ios8-b7-nsnumberformatter-bug/
+ (NSString *)iOS8CurrencyForAmount:(NSNumber*)number{
#warning remove this once iOS8 nsnumberformatter bug fixed

    NSString *numberString= [NSString stringWithFormat:@"€ %@", number.description];
    NSUInteger length= numberString.length;

    if ([numberString containsString:@"."]){
        // catch when only one significant digit, e.g. 1.2 -> 1.20:
        if ((length-2 > 0) && [[numberString substringFromIndex:length - 2] containsString:@"."]){
            return [NSString stringWithFormat:@"%@0", numberString];
        }
    }
    else{
        // no decimal place at all. Just append .00
        return [NSString stringWithFormat:@"%@.00", numberString];
    }

    return numberString;
}

EDIT

My bad - the minimumSignificantDigits and maximumSignificantDigits properties don't even need to be set, so if you strip them off then all is right again.

Remove iBook citations with a keyboard shortcut

Whilst reading @AshFurrow's excellent book on Functional Reactive Programming (do read it, it's an refreshingly different way of going about writing Obj-C), I was finding that I was required to copy/paste a lot of code snippets from the e-book into AppCode.

This is not a nice process: if you're reading it via the PDF, Preview.app doesn't correctly OCR the line spaces and what you paste into your IDE is a horribly mangled form of the code which won't compile and has to be tediously repaired. (it also unnecessarily copies the line numbers).

If you're reading via the Kindle app, that flat-out prevents you from copying any text at all from the book (fuck you, Amazon).

So that leaves the iBooks for OS X app, which does a great job at copying the text, but encases it in a citation block like so:

β€œRAC(self.imageView, image) = [[RACObserve(self, photoModel.thumbnailData)  2     ignore:nil] map:^(NSData *data) { 3   return [UIImage imageWithData:data]; 4 }];”

Excerpt From: Ash Furrow. β€œFunctional Reactive Programming on iOS.” iBooks.

This is a feature built into iBooks which cannot be turned off - doh, resulting in:

After a while of removing all that each time I wanted to paste a snippet, I relented and wrote an Automator script to strip this out whilst it's in the PasteBoard:

Here is the script: https://gist.github.com/iandundas/7863c6c248f76e14a3a8

After you have saved the Automator script shown in the screenshot, then you can hook it up to a keyboard shortcut in System Preferences:

Now when I paste, I get:

RAC(self.imageView, image) = [[RACObserve(self, photoModel.thumbnailData) 
    ignore:nil] map:^(NSData *data) {
    return [UIImage imageWithData:data];
}];

Much better. It's:

  • removed the line numbers
  • removed the surrounding quotation marks
  • removed the citation text

Now it's clean enough to paste into your IDE.