How to run SwiftLint autocorrect on each Git commit

SwiftLint was developed by the nice folks @realm. It's a great open-source tool for establishing and enforcing a formal coding style in Swift. It runs on the command-line, but it can be hooked into Xcode directly too. It also boasts an "autocorrect" feature, which sweeps through your code and automatically fixes the most trivial violations (e.g., colon positioning, double white spaces, etc.). I created a Git commit hook which does exactly this, every time a team member makes changes.

Read More

Abolish Retain Cycles in Swift with a Single Unit Test

Can't believe we're still dealing with this in 2017? Well, that makes two of us. While retain cycles are easy to fix, they're also hard to spot while eyeballing a codebase. Recently, I've found that a single unit test can provide solace. With just a few lines of code, it runs continuously as you make changes, all the while verifying you haven't introduced any new memory leaks.

Read More

Loading custom fonts programmatically in Swift 3

How do you include custom fonts in your application, if they don't reside in the main bundle? In this case, loading them through the conventional PLIST method doesn't work, and you will need to resort to CoreGraphics to register them programmatically. 

Typefaces are an essential part of good design. On iOS, custom fonts can be added to apps through a somewhat convoluted process. Chris Ching has a good write-up on the topic, but in short: ensure the font files are properly included in your app's target and declare them in your app's Info.plist ("Fonts provided by application"). This works well in the straightforward case where the fonts are simply embedded into the main app bundle.

You quickly run into the limits of the PLIST-based registration method when they live outside of the main bundle, e.g. in a separate .framework. In this case, simply register the fonts using the older CoreGraphics APIs.

Marco Arment described the approach on his blog back in 2012, but the example code he lists is Objective-C. Fortunately, the Swift version of this code is much less cumbersome than its Obj-C counterpart, as less C-trickery is required:

// Load bundle which hosts the font files. Bundle has various ways of locating bundles.
// This one uses the bundle's identifier
guard let bundle = Bundle(identifier: "some.framework.identifier")
else { return }

// List the fonts by name and extension, relative to the bundle
let fonts = [
    bundle.url(forResource: "gotham_book", withExtension: "ttf"),
    bundle.url(forResource: "gotham_medium", withExtension: "ttf")
]

// Iterate over the resulting urls, filtering out nil-values with .flatMap()
for url in fonts.flatMap({ $0 }) {
  // Create a CGDataPRovider and a CGFont from the URL.
  // Register the font with the system.
    if let dataProvider = CGDataProvider(url: url as CFURL) {
        let font = CGFont(dataProvider)
        CTFontManagerRegisterGraphicsFont(font, nil)
    }
}

Just make sure you don't forget to remove any duplicate PLIST declarations, or your app will throw an exception at startup.

Update

@sveinhal in the comments suggested this functional rewrite of the above code, which is way more succinct if that's your cup of tea:

let fonts = [
bundle.url(forResource: "gotham_book", withExtension: "ttf"),
bundle.url(forResource: "gotham_medium", withExtension: "ttf"),
]

fonts
.flatMap { $0 }
.flatMap { CGDataProvider(url: $0 as CFURL) }
.map(CGFont.init)
.forEach { CTFontManagerRegisterGraphicsFont($0, nil) }

Filling the KVO gap in Swift with ReactiveCocoa

How do you do Key-Value Observing in Swift? Can you? And what about just using Objective-C's native KVO mechanism? What follows is a gentle introduction to ReactiveCocoa's unsung hero of property observation: Property (and MutableProperty). 

Matt Thompson explained the ins and outs of KVO in exasperating detail in 2013 for NSHipster. In summary, let's just say it's a messy Objective-C API, which still happens to work in Swift today. Aside from the occasions where you can't do without (NSProgress anyone?), I would advise against using it. Its complexity makes it prone to bugs. But Swift doesn't offer a native equivalent, you say...

I hear you, but suppose you could simply do something like this, to listen for changes and reload a table view in response, picking up any new items:

override func viewDidLoad() {
    super.viewDidLoad()

    viewModel.drafts.signal.observeValues { [weak self] drafts in
        self?.tableView.reloadData()
    }
}

Meet ReactiveSwift Properties

I would be omitting an important tidbit about Swift's native observation capabilities, if I neglected to mention the didSet and willSet property observers. With enough boilerplate code, you can definitely cobble together something akin to KVO. You could, for instance, listen to the property changes yourself with didSet and re-dispatch these events over a delegate. Purists will prefer this approach, because no magic is involved, and no third-party libraries are required.

However, ReactiveSwift aims to encapsulate all this complexity by means of a singular concept, called Property. Simple, because at its core, Property is merely a value box, with a means to notify others of its changes. Here's the pared-down protocol, taken from the 1.0 release of ReactiveSwift (github.com/ReactiveCocoa/ReactiveSwift/blob/1.0.0/Sources/Property.swift):

public protocol PropertyProtocol: class, BindingSourceProtocol {
	associatedtype Value

	var value: Value { get }
	var producer: SignalProducer<Value, NoError> { get }
	var signal: Signal<Value, NoError> { get }
}

The producer and signal properties are the actual observables you subscribe to for changes. Why the distinction? The RxJS README has a nice summary:

"Cold observables start running upon subscription, i.e., the observable sequence only starts pushing values to the observers when Subscribe is called. Values are also not shared among subscribers. This is different from hot observables such as mouse move events or stock tickers which are already producing values even before a subscription is active."

When applied to ReactiveSwift, cold observables correspond to signal producers, while hot signals are represented by "regular" signals. In the context of properties, this boils down to:

  • Starting the producer will emit the property's initial value, as well as any subsequent changes;
  • Observing the signal will only emit the values changed after the observation was started.

Usage

The concrete implementations of PropertyProtocol are contained by the classes Property and MutableProperty. Generally, you'll be using the mutable variant, since it allows you change the property's underlying value, thus triggering change notifications. The easiest way is to forego optionals and use let constants instead:

// Defining the property
let avatarUrl = MutableProperty("https://httpbin.org/image/jpeg")

// Setting the property's value
avatarUrl.value = "..."

// Listening for changes, without the initial value
avatarUrl.signal.observeValues { url in
}

// Listening for changes, including the initial value
avatarUrl.producer.startWithValues { url in
}

Data binding

Data binding is a means of tying properties to UI components, so that the component updates itself whenever the property changes. Contrary to AppKit, iOS' UIKit has no notion of data binding. ReactiveCocoa exposes data binding through a single custom property: a less-than sign followed by a tilde.

<~

Its shape emphasizes the binding's unidirectionality. The following example clearly expresses the fact that the artist name is being set on the artist label's text property whenever it changes, not the other way around:

// Hook up bindings in your controller's viewDidLoad()
func viewDidLoad() {
    super.viewDidLoad()
    artistLabel.reactive.text <~ viewModel.artistName
}

// Example implementation of this viewModel (details omitted for brevity)
class ViewModel {
    let artistName = MutableProperty<String?>(nil)
}

Data binding is a declarative way to express relationships between data and UI components. It reduces the cognitive overhead of manually assigning values. Code locality is also improved, as this approach centers binding logic into a single place. 

ReactiveCocoa & ReactiveSwift

What's the difference? With ReactiveCocoa 5, the core team decided to split up the codebase, in order to more clearly delineate each component's responsibility and scope. This division also allows framework users to more easily cherrypick which modules they need in their projects.

  • ReactiveSwift: The new kid on the block. This is a pure-Swift implementation of the reactive API. It provides all the nuts and bolts, including Signals, SignalProducers, Properties, Actions and Bindings.
  • ReactiveObjC: ReactiveSwift's Objective-C-based sibling. This is essentially ReactiveCocoa 2.0 and remains in maintenance mode.
  • ReactiveCocoa: The connecting piece between UIKit and ReactiveSwift. It provides all of the reactive extensions for UIKit components and exposes binding targets for them. It also introduces Triggers, a means for converting Objective-C selectors into signals. You can also wrap good ol' ObjC KVO with signals, so they can be interspersed with ReactiveSwift signals and producers.
  • ReactiveObjCBridge: Bridges the ReactiveCocoa 2.0 API with the ReactiveSwift API, so ReactiveObjC remains accessible from Swift, enabling interoperability with old code.

Why Swift is making me feel blue

I'm just about blue in the face complaining about it, too. So bear with me if you've heard all this before. I promise I'll stop ranting after this post, and move on to happier topics ;-).

Slow as molasses

I wrote this post while waiting for Xcode to finish compiling

I realize this may be caused by a combination of issues. Perhaps the Swift compiler is not optimized yet. Perhaps it's just the generally awful state of the Xcode toolchain. Whichever the culprit, the end result remains equally as enervating... I am referring to Swift's complete and utter slowness with regards to code compilation.

If you've done any serious Swift development of late, you know that incremental Swift compilation is a lie. All but the most trivial changes trigger complete rebuilds, resulting in insane waiting times between builds. Apple supposedly set out to resolve this issue with Xcode 8.2.1, but I believe they merely put out a lopsided mitigation in lieu of an actual fix.

With no real insight into how Xcode determines the scope of the required recompilation, it appears Xcode gets into trouble as soon as you alter the external interface of a (any) source file. This includes adding new functions, modifying existing function signatures, altering the inheritance chain and the like (which has to be 75% of the time, right!).

I have been struggling with this particular rough patch in Swift for the better part of a year and resulting frustration has even driven me to reconsider Objective-C. Folly, I know! On a more serious note, though: the current compiler/toolchain performance is a severely limiting factor on my overall coding productivity. Stuff takes longer to get done. My MacBook's fans are ablaze all day long. And I drift off to Facebook and Twitter in between builds and struggle to pick up where I left off 😫🤕.

This is not to say that I don't absolutely prefer Swift over Objective-C (and any other higher-level language, for that matter). I love the enthusiastic community surrounding it. The general direction the open-source project is taking the language is equally as encouraging. But its newly-fangled-ness makes the fledgling language pretty rough around the edges. Perhaps the 1.0 moniker was bestowed on it too soon? Perhaps it's my fault for being an early adopter? Maybe. All I know is that this part of Swift still needs quite a bit of work. I just hope enough of the smart minds in the Swift community are looking as much inward, as they are forward.

SourceKit hell

SourceKitService is the memory-hungry background process which powers Xcode's syntax highlighting and code analysis. Even though it has dramatically improved since Swift 2, its performance remains a big issue. Too often, code will be marked as erroneous or no syntax highlighting will be available at all. Despite being decoupled at the process-level, Xcode still depends strongly on SourceKitService. Autocompletion and ⌘-click navigation, for instance, are severely impacted by SourceKit bugs. A rebuild often resolves the bug, albeit terribly slowly, because of my earlier gripe...

As much as I love to bask in the glory that is Swift's newness and road to world domination, I also need things to work, and waiting around for a computer isn't really my idea of "working". But I -- and no doubt many others -- will continue to put up with it.

Because we believe in the Swift project, right?