A Very Narrow Usage of Storyboards

Lately I’ve been struggling to balance the pros and cons of various view controller initialization techniques. There are three, none of which are perfect:

Lately, the projects I’ve been working on have had pretty heavy AutoLayout requirements. As such, it’s been easiest to build the user interface logic using a Storyboard. But the Storyboard approach makes it really hard to pass in dependencies in a simple, reliable fashion.

Until Apple provides a better solution, my current strategy is to provide a static factory method that takes as arguments all the dependencies that need to be passed in:

static func newFromStoryboard(foo: FooDependency, bar: BarDependency) -> MyViewController

In addition, I make the relevant instance variables private, so that they can only be set from inside the file:

private var foo: FooDependency!
private var bar: BarDependency!

The factory method instantiates the view controller from the correct storyboard, and then sets all the dependencies. I only use one view controller per storyboard, and never use segues.

This is not the most elegant approach I can imagine, but I believe it’s the least inelegant approach made possible within the current state of the UIKit framework and Swift.

|  27 Apr 2016




Don DeLillo on Chickenshit White UI Design

We ran into Murray Jay Siskind at the supermarket. His basket held generic food and drink, nonbrand items in plain white packages with simple labeling. There was a white can labeled CANNED PEACHES. There was a white package of backon without a plastic window for viewing a representative slice. A jar of roasted nuts had a white wrapper bearing the words IRREGULAR PEANUTS. Murray kept nodding to Babette as I introduced them.

“This is the new austerity,” he said. “Flavorless packaging. It appeals to me. I feel I’m not only saving money but contributing to some kind of spiritual consensus. It’s like World War III. Everything is white. They’ll take our bright colors away and use them in the war effort.”

From White Noise.

|  26 Apr 2016




I admit I never understood what Manton found appealing about microblog posts until today, a week...

I admit I never understood what Manton found appealing about microblog posts until today, a week into my Giving Up On Twitter experiment, inspired by Seth. Seth’s feelings about Twitter caught me off guard. I think I’ve been having a similar experience. So I deleted all but Tweetbot, disabled all but the minimal socially-acceptable push notifications, and moved it to a third home screen folder.

|  25 Mar 2016




Imagining a First-Party Swift KVO Replacement

My last post got me thinking: if Apple were to add a KVO-like service to Swift, what would it look like? I wish I understood more about how programming languages are created, and how compilers work. What follows isn’t really a serious proposal, but just a sketch of what I would personally want to use as a practicing software developer.

What if every Swift class received an implicit, protected member with a reserved name like observables which provided a means to register closures as observers for changed values? An example usage might look like this:

let tweet = Tweet(text: “Hi.”)
tweet.observables.isLiked.addObserver { (oldValue, newValue) -> Void in
    // this is otherwise just a standard closure, with identical
    // memory management rules and variable scope semantics.
    print(“Value changed.”)
}
tweet.isLiked = true // Console would log “Value changed.”

The observables property would be implied, just like self. It would be an instance of some ad-hoc generated Swift class created by the compiler at compile time. For every observable property of the owning class, this observables class will have a corresponding observable property. So if you created a class like this:

class Tweet {
    var isLiked: Bool = false
    let text: String
    
    init(text: String) {
        self.text = text
    }
}

The Swift compiler would generate a class like this and assign it to the observables property for Tweet:

class Tweet_SwiftObservables {
    let isLiked = Observable<Bool>()
}

The Tweet_SwiftObservables class name would be auto-generated based on the class name of the target class. Notice that only the isLiked property is carried over, since the text property of Tweet is a let, not a var.

The isLiked member of Tweet_SwiftObservables is an instance of a generic Observable<T> class, whose implementation would be something like the following (though, of course, more nuanced):

class Observable<T> {
    typealias Observer = (oldValue: T?, newValue: T?) -> Void
    private var observers = [UInt: Observer]()
    
    func addObserver(observer: Observer) -> Uint {
        let token: Uint = 0 // generate some unique token
        self.observers[token] = observer
        return token
    }
    
    func removeObserverForToken(token: Uint) {
        self.observers[token] = nil
    }
}

The money shot is the addObserver() method. This method accepts a single Observer argument, which is just a simple closure. It would follow all the existing rules of memory management and variable scope as any other closure. addObserver() returns a unsigned integer token that can be used to remove the observer at a later time.

What I like about my idea is:

|  1 Jan 2016




NSNotificationCenter is Probably an Anti-Pattern

This week’s iOS Dev Weekly linked to a tweet from Ben Sandofsky about an important change to NSNotificationCenter in iOS 9:

In OS X 10.11 and iOS 9.0 NSNotificationCenter and NSDistributedNotificationCenter will no longer send notifications to registered observers that may be deallocated. If the observer is able to be stored as a zeroing-weak reference the underlying storage will store the observer as a zeroing weak reference, alternatively if the object cannot be stored weakly (i.e. it has a custom retain/release mechanism that would prevent the runtime from being able to store the object weakly) it will store the object as a non-weak zeroing reference. This means that observers are not required to un-register in their deallocation method. Link.

I can’t remember where I heard the following fact (I think it was during one of the WWDC 2015 talks), but it’s my understanding that a deallocated-without-unregistering NSNotificationCenter observer is one of the top causes of crashes in third-party iOS/OS X software. Assuming this is true, a thought struck me today: how much less common would this crash have been if there had been an easier alternative than KVO all this time?

In Foundation, there are only two first-party ways to propagate model changes from one to many observers: KVO and NSNotificationCenter. Both of them are prone to cause crashes when misused, but I’d argue that KVO is harder to use correctly. It’s not unreasonable to imagine that many developers opt for NSNotificationCenter as the least bad option.

It may sound surprising to some that I’d refer to NSNotificationCenter as a “bad” option. I should clarify that I think NSNotificationCenter is a fine API when used for events of a truly global nature. An argument for or against NSNotificationCenter is like an argument for or against a singleton. As I’ve joked on Twitter:

Use a singleton when you need the Sun, not an overhead lamp.

Similarly, I think NSNotificationCenter is best suited for events whose origin is so far outside the scope of local control flow that it would be awkward or even silly to use anything else. The NSNotificationCenter version of my singleton tweet is:

NSTheSunDidRiseNotification, not NSSomebodysPassengerPushedTheFlightAttendantButtonNotification.

In practice I have a hard time justifying the use of NSNotificationCenter for anything besides events vended by the OS, like UIKeyboardWillShowNotification.

I often see NSNotificationCenter used as a clearing house for all the one-to-many relationships between model objects and observers in an app. I think this is probably an anti-pattern. This pattern obligates observers to decide when to ignore notifications.

Consider a Twitter client with a TweetWasLikedNotification. The observers for that notification not only need to know the ID of the liked tweet, but also the local account from which that like action was taken, and/or perhaps the NSManagedObjectContext to which the tweet belongs, etc. Global knowledge belongs at a higher layer in the application. Better still is a design that couples model and observer more closely with an explicit relationship (perhaps a delegate protocol) that doesn’t require such knowledge in the first place.

I have considered using a custom center, instead of the defaultCenter() singleton, but that seems like a half-baked implementation of a design that would be better expressed via a weak-referencing collection of SomeCustomObserverProtocol delegates.

Until Apple provides a Swift-native, first-party way to implement a one-to-many observer pattern, I will continue to use NSObject subclasses and KVO. I’ve been trying to think of ways to abstract out the particulars of NSObject/KVO relationships, keeping the higher-level APIs cleaner and more friendly. Here’s an example of what I mean, posted to GitHub. For a direct-download link of the Xcode playground, click here. I haven’t tried this in production yet, but the idea is to map NSObjects to adapter/observers who produce “view model” structs in response to KVO updates, passing those structs onto their delegates. This lets me use value types instead of the actual model objects for UI updates, without having to abandon KVO as the underlying infrastructure.

|  1 Jan 2016