I often get a better picture of a type’s purpose from knowing what its instance variables are. Once you know the underlying structure of that type, it’s more obvious how to use it. The converse is also true: it can sometimes be hard to figure out what exactly an object is for, without seeing the layout of its members. This is especially apparent with Apple’s closed-source classes.

A great example of this is NSDate. When I started programming, I had a tough time figuring out how to use the NSDate and all of its corresponding sibling objects, like NSDateComponents, NSDateFormatter NSCalendar. Why do you have to use NSCalendar to add 2 days to date? The boundaries between these classes seem arbitrarily drawn, and that makes it hard to know where to look to find any specific functionality you’re looking for.

The key revelation for me was understanding what NSDate really was under the hood, which made all the rest of the pieces fall together. NSDate is just a fancy wrapper around a double. That’s it. And a close reading of the docs reveals this fact:

NSDate objects encapsulate a single point in time, independent of any particular calendrical system or time zone.

All NSDate does is store a double representing the number of seconds since 00:00:00 UTC on January 1, 2001. This number of seconds has nothing to do with timezones, days of the week, months, daylight savings time, leap seconds, or leap years. If the calculation can be done with just the number of seconds since that reference date, it goes on NSDate. Otherwise, it goes somewhere else.

Examples of things that can be done with just this double are comparison (earlierDate, laterDate), equality, and time interval calculations (which also returns a number of seconds). distantFuture and distantPast are obvious now too, they’re just the largest expressible doubles, in positive and negative forms.

For other stuff, you have to go to other classes and objects. For example, adding one day to a moment in time, while it can done by just adding 24*60*60 seconds to an NSDate, is best handled via NSCalendar, to avoid running afoul of issues with Daylight Savings Time, leap seconds/days, and other non-standard issues that can crop up with time. This blog post lays out the case for using NSCalendar for these calculation.

Because NSDate doesn’t store any information about the expected month of a particular date, if you want to change that month, you have to use an object that knows about and can split apart the various “components” that make up a date. For this, we use a NSDateComponents object. I find that thinking about how I might write a similar class can help me understand what it’s for and how its layout works. Take a look at the public interface for NSDateComponents and see if you can figure out how its data might be stored internally.

I found another interesting example of using an object’s property storage layout to learn things about the nature of that object when I was working on my Promise library. If you look at the properties that each of my Promise objects stores, you’ll see three things:

public final class Promise<Value> {
    
    private var state: State<Value>
    private let lockQueue = DispatchQueue(label: "promise_lock_queue", qos: .userInitiated)
    private var callbacks: [Callback<Value>] = []

Each promise has its current state (such as .pending, fulfilled, or .rejected), a queue to ensure thread-safety, and an array of callbacks to call when the promise is either fulfilled or rejected.

After writing my library, I looked at some Signal/Observable implementations to see if I could understand them. I found JensRavens/Interstellar to be the most straightforward. I look at the instance properties of each of its Signal objects, and I found a very similar structure:

public final class Signal<T> {
    
    private var value: Result<T>?
    private var callbacks: [Result<T> -> Void] = []
    private let mutex = Mutex()

Something to store the current state, something to store the callbacks, and something to store the thread-safety primitive. The order is different, and they used a mutex instead of a queue, but it’s otherwise identical. The only difference between these two types is a semantic one: promises can clear their callbacks when they’re completed (releasing them and the variables they capture), and signals must keep their callbacks around.

I think this principle can also help in the design of your own type too. Take a look at the properties on an object that you’re working on. Does each property have a purpose? Does it contribute to the overall identity of the object? Are there properties that are used in some instances of that type, but not others? If so, those properties might belong somewhere else. Making sure that the instance variables available on a type are tightly controlled and used fully ensures that our object has a well-defined purpose in your application.

When firing network requests, there are often many side effects that need to take place. Side effects are poison for testability, however, and may vary from app to app and request to request. If we can create a system where we can create and compose these side effects together, we can increase the testability and other factors.

Imagine a very simple network client:

final class NetworkClient {

    let session: URLSession
	
    init(session: URLSession = URLSession.shared) {
        self.session = session
    }

    func send<Output: JSONInitializable>(request: Request<Output>) -> Promise<Output> {
        let urlRequest = RequestBuilder(request: request).urlRequest
        return session.data(with: urlRequest)
            .then({ data, response in
                let json = try JSONSerialization.jsonObject(with: data)
                return Output(json: json)
            })
      }
}

This class wraps a URLSession. It has a send method that accepts Request objects that have some associated phantom type Output that conforms to JSONInitializable. The send function returns a promise with the same type as Output. In the body of the send method, a URLRequest is built using the RequestBuilder type, and that request is sent via the URL session. The data that is returned from the network request is parsed as JSON, and hydrates a model, which is the value inside the returned promise.

This network client is greatly simplified (namely, I left out some optional handling stuff), but is basically the code I want to work with.

This class right now is great. It’s a simple object that doesn’t touch anything global (minus the network, gated through the URLSession), and is easily testable. We could wrap the URLSession in a protocol, inject it in the NetworkClient initializer, and mock it in our tests, and test the logic around constructing an object from some JSON response. Testable network code!

The trouble here is that while it does do plenty of good stuff, there’s still lots that it doesn’t do. For example, we might want it to:

  • register a background task with the application, so that the network request can keep working after the user presses the home button
  • show and hide the application’s network activity indicator
  • add a specific header for authorization with some API

We could add all of these things to our NetworkClient class, but each of them touches some piece of global state or singleton. The first one touches the UIApplication singleton, the second, a shared counter, and the third, some form of storage that keeps track of the auth token.

If we added all of these globals and special cases, it’ll be a lot harder to test this object. We’ll have to mock up and inject each of these globals in separately, and our tests will get that much more complicated.

These three behaviors are expected to fire on every network request, but other requests will have request-specific behaviors that would ideally be reusable. For example, many (but not all) requests will need error handling, to let the user know that some action they took didn’t go through successfully. Other requests will need to save things to Core Data, and I’d ideally like the network client to know nothing about Core Data. While I won’t be focusing on examples of request-specific behaviors here, I’ll show the code for how to integrate them.

I want a way to decouple these behaviors implementation details from the network client, so that we can test the client separately from each of the behaviors.

Let’s define a request behavior with a protocol:

protocol RequestBehavior {
	
    var additionalHeaders: [String: String] { get }
			
    func beforeSend()
	
    func afterSuccess(result: Any)
	
    func afterFailure(error: Error)
    
}

The protocol provides a pretty boring default implementation for each method:

extension RequestBehavior {
	
    var additionalHeaders: [String: String] {
        return [:]
    }
	
    func beforeSend() {

    }
	
    func afterSuccess(result: Any) {

    }
	
    func afterFailure(error: Error) {

    }
    
}

The basic idea is each behavior gets callbacks when specific network events occur, and they can execute code. Two things will be useful for us as we develop this: an “empty” request behavior that doesn’t do anything, and a request behavior that combines many request behaviors. The “empty” behavior inherits all the implementations from the protocol extension, and the “combined” behavior stores an array of behaviors and calls the relevant method on each behavior:

struct EmptyRequestBehavior: RequestBehavior { }

struct CombinedRequestBehavior: RequestBehavior {

    let behaviors: [RequestBehavior]

    var additionalHeaders: [String : String] {
        return behaviors.reduce([String: String](), { sum, behavior in
            return sum.merged(with: behavior.additionalHeaders)
        })
    }
	
    func beforeSend() {
        behaviors.forEach({ $0.beforeSend() })
    }

    func afterSuccess(result: Any) {
        behaviors.forEach({ $0.afterSuccess(result: result) })
    }

    func afterFailure(error: Error) {
        behaviors.forEach({ $0.afterFailure(error: error) })
    }
}

These are very abstract for the moment but will become useful soon.

Next, we need to modify our network client to call the methods in our request behavior at the right time.

final class NetworkClient {

    let session: URLSession
    
    let defaultRequestBehavior: RequestBehavior
	
    init(session: URLSession = URLSession.shared, defaultRequestBehavior: RequestBehavior = EmptyRequestBehavior()) {
        self.session = session
        self.defaultRequestBehavior = defaultRequestBehavior
    }

    func send<Output: JSONInitializable>(request: Request<Output>, behavior: RequestBehavior = EmptyRequestBehavior()) -> Promise<Output> {
        let combinedBehavior = CombinedRequestBehavior(behaviors: [behavior, defaultRequestBehavior])
        let urlRequest = RequestBuilder(request: request, behavior: combinedBehavior).urlRequest
        combinedBehavior.beforeSend()
        return session.data(with: urlRequest)
            .then({ data, response in
                let json = try JSONSerialization.jsonObject(with: data)
                let result = try Output(json: json)
                combinedBehavior.afterSuccess(result: result)
                return result
            })
            .catch({ error in
                combinedBehavior.afterFailure(error: error)
            })
    }
}

The defaultRequestBehavior from the client and the behavior for the specific request both default to a new EmptyRequestBehavior, so that they become effectively opt-in. Our network client combines the behavior for the individual request and the behavior for the whole client. It passes that to the RequestBuilder so it can use the additionalHeaders, and then it calls beforeSend, afterSuccess, and afterFailure at the appropriate times and with the appropriate values.

With this simple separation of request and side effect, it’s now possible to test the client separately from each the behaviors we might want to add to it. These behaviors themselves, since they’re their own objects, can be easily instantiated and tested.

Let’s take a look at at the behaviors I mentioned above. First, registering a background task for each network request:

final class BackgroundTaskBehavior: RequestBehavior {

    private let application = UIApplication.shared

    private var identifier: UIBackgroundTaskIdentifier?

    func beforeSend() {
        identifier = application.beginBackgroundTask(expirationHandler: {
            self.endBackgroundTask()
        })
    }

    func afterSuccess(response: AnyResponse) {
        endBackgroundTask()
    }

    func afterFailure(error: Error) {
        endBackgroundTask()
    }

    private func endBackgroundTask() {
        if let identifier = identifier {
            application.endBackgroundTask(identifier)
            self.identifier = nil
        }
    }
}

While these background tasks are often only registered at the time the app is closed, and usually a single one is registered, you can register as many as you want, at any time. Because this behavior requires the maintenance of state, it’s especially suited to being its own object, and thus a prime candidate for a request behavior. Testing this behavior involves wrapping the UIApplication in a protocol, injecting it in an initializer, and confirming with a mock that the right methods were called at the right times.

Next, let’s look at the network activity indicator.

class ActivityIndicatorState {

    static let shared = ActivityIndicatorState()
    
    let application = UIApplication.shared
    
    var counter = 0 {
        didSet {
            application.isNetworkActivityIndicatorVisible = NetworkActivityBehavior.counter == 0
        }
    }
}

class NetworkActivityIndicatorBehavior: RequestBehavior {
    
    let state = ActivityIndicatorState.shared

    func beforeSend() {
        state.counter += 1
    }

    func afterFailure(error: Error) {
        state.counter -= 1
    }

    func afterSuccess(response: AnyResponse) {
        state.counter -= 1
    }

}

This behavior is another one that’s typically impossible to test. Now that it’s broken up into two objects, instead of being embedded in the NetworkClient, it’s now possible. Inject the application singleton (wrapped in a protocol, passed into the initializer) into ActivityIndicatorState, and you can test that it correctly turns the network activity indicator on and off by changing the value of the counter. Inject a ActivityIndicatorState (also wrapped in a protocol, passed into the initializer), and you can test the incrementing and decrementing of counter property as well.

Finally, let’s look at how we might bring the global state of an auth token into a request behavior.

struct AuthTokenHeaderBehavior: RequestBehavior {

    let userDefaults = UserDefaults.standard

    var additionalHeaders: [String : String] {
        if let token = userDefaults.string(forKey: "authToken") {
	        return ["X-Auth-Token": token]
	     }
        return [:]
    }
    
}

This one is simple enough that I might not test it, but nevertheless, something that was really hard before is a lot simpler now. Inject the standard UserDefaults object (surprise, wrapped in a protocol again), and test that it correctly returns the header dictionary. One more test for if the UserDefaults doesn’t have the key in question, and you’re all done.

To access the network client in an iOS application, it’s typically done with a global accessor. Because this client requires many lines of initialization, I might put it in an immediately-executed closure:

enum SharedNetworkClient {
    static let main: NetworkClient = {
        let behavior = CombinationRequestBehavior(behaviors: [
            AuthTokenHeaderBehavior(),
            NetworkActivityBehavior(),
            BackgroundTaskBehavior(),
            ])
        return NetworkClient(behavior: behavior)
    }()
}

I’ve also started putting singletons in their own namespace (called SharedX), instead of in the type itself, to help remind me that singletons should just be objects, and that they aren’t exempt from being testable objects and good citizens.

A few final notes: the network library Moya has a feature similar to this called “plugins”. While my implementation is a little bit different, it’s a very similar idea. Moya’s plugins only operate on a per-client basis, adding behaviors that operate per-request is also very useful for performing side-effects, like saving to some form of persistence or cache, or presenting an error.

You may find that you need other methods on your request behavior, which you should feel free to add. One that I omitted here for brevity is:

func modify(request: URLRequest) -> URLRequest

This function lets you mutate the URLRequest in any way that you want, even returning a totally different URLRequest, if you want. This is obviously a powerful and dangerous action, but for some requirements it is useful and even necessary.

Network code is typically hard to maintain, because it touches an inherently global resource, which lends itself to tough-to-test singleton designs. Request behaviors are a useful way of separating the code that sends requests from any side-effects that need to happen during that request. This little abstraction simplifies network code, adds reusability for per-request behaviors, and vastly increases testability.

Chris Dzombak and I started a podcast this summer called Fatal Error. This Monday, we published the 10th and final episode of the first season.

Each episode, we covered a different programming pattern. We covered coordinators, view models, promises, and signals. We discussed singletons, the single-responsibility principle, domain-driven design, and testing. We capped the season off with a discussion of why we think caring about code is the same as caring about your prodcuct.

I wasn’t sure how it would turn out, but I’m really pleased with the work that Chris and I did on it. Our episodes are between 30 minutes and an hour, and we post a new one every other week.

We’re taking a short break, and we’ll be back with Season 2 in early January. We have some cool stuff planned, and we hope you’ll join us!

Bryan Irace wrote a great post a earlier this year, detailing how to measure the compilation time of the swift functions that you write. It’s a great technique for spot checking your slow functions, but you’ll have to remember to run it every few months, to catch any new slow functions you write.

In May, Jordan Rose added a Swift flag for emitting warnings whenever a function takes longer than some threshold to compile. You can leave this flag enabled in your project, and it will warn you whenever any slow functions are added to the project.

To add the flag:

  1. Navigate to your target in Xcode (not the project)
  2. Click the “Build Settings” tab
  3. Make sure that “All” settings are being shown, not “Basic”
  4. Scroll to (or search for) “Other Swift Flags”
  5. Add two flags: -Xfrontend and -warn-long-function-bodies=100, where 100 is the number of milliseconds you’d like the warning threshold to be
  6. Compile your project

When you compile, you’ll notice some new warnings. They look something like:

Getter ‘uniqueID’ took 105ms to type-check (limit: 100ms)

You can click on the warning to jump to the function in question. Rewrite it to take less time to compile.

Sadly, in the commit message adding this feature, Jordan writes,

As a frontend option, this is UNSUPPORTED and may be removed without notice at any future date.

This feature is very useful, and I hope it stays around as long as Swift compile times are flaky.

Thanks to Olivier, Caleb and Sam.

What if arrays in Swift couldn’t be empty?

Hear me out: maybe Swift should have been designed with empty arrays being impossible. It’s madness, right? What other language has arrays that can’t be modeled as empty?

However, Swift already changes some of the rules from older languages like C. For example, there’s no break required in switch statements, opting for the more explicit fallthrough to combine cases instead. There’s no ++ operator, either. It’s confusing, duplicative, and ultimately the language is better without it.

Swift also differs from C by requiring explicit nullability. Swift lets you describe to the type system whether a single value is “empty” or not, using the Optional type. You can say whether you have a view controller, or something that might be a view controller, and might be .none. The type system can then check your work in all places, ensuring that the value is never missing when you expect it to be there.

Doubly Empty

When optionals and arrays interplay, however, you have two ways of expressing emptiness: nil and the empty array.

This can cause confusion, for example, when checking if an optional array is either nil or empty. For example, you might expect optional chaining to be effective, since it’s so useful in other parts of Swift. optionalArray?.isEmpty, however, returns an Optional<Bool>, which really distills down to the essence of a confused type. The type system will reject expressions that evaluate to optional bools in if statements.

optionalArray == [] will compile, but returns false for the case when the array is nil, which isn’t the expected behavior. You’re left with a few other choices that are all correct, but unwieldy:

if optionalArray == nil || optionalArray == [] {

if let array = optionalArray, array.isEmpty {

if (optionalArray ?? []).isEmpty {

if optionalArray?.isEmpty != false {

if optionalArray?.isEmpty ?? false {

The easiest way to get around this is to remember to never store optional arrays as properties. I’m pretty strict about this rule, making sure I don’t mix different types of emptiness. I also apply it other other types that can be “empty” as well — dictionaries, strings, booleans, sets, and sometimes numbers. Having to check two forms of emptiness is something I never want to do.

While its easy to follow this rule, for example, in the properties of a class, it’s not really possible to follow it in all cases. For example, getting an array property from an optional object will result in an optional array.

let wheels = optionalCar?.wheels // expression has type [Wheel]?

Getting a value out of a dictionary is the same.

let wheels = dictionary["wheels"] as? [Wheel]

You have to remember to tack on ?? [] to each of these expressions.

We just came from a world where you couldn’t separate the concept of a nullable view controller from a view controller to the type system. Gaining that ability simplified lots of expressions, reduced crashes, and generally clarified our code.

If the Array type couldn’t be empty, then optional arrays would represent empty arrays, and non-optional arrays would always have at least one item in them. One of the two forms of emptiness would be impossible, and any code that tried to use the other form would simply wouldn’t compile.

Modeling

Non-empty arrays are also useful for modeling. Sometimes it’s useful to express to the type system that a given array can never be empty. For example, perhaps your User class is modeled as having many email addresses, but shouldn’t be valid if the user has no email addresses. Expressing that to the type system would be awesome, but we currently can’t do that. Other examples:

  • A Country must have at least one City.
  • An Album must have at least one Song.
  • A Building can’t exist without at least one Floor.

The examples abound.

If the Array type couldn’t be empty, these relationships and their constraints would all be expressible to the type system, and you’d be prevented from removing the last item from arrays.

Expressions

With the advent of the Optional type, many expressions became simplified. When you know that a type can’t ever be null, you can skip certain checks and treat it in a more straightforward way. It’s the same with non-empty arrays. Currently, methods on the Collection protocol, like first, last, max and min return optionals, purely to handle the case that the array is empty.

There have been multiple cases where I knew an array was modeled such that it should never be empty, and when calling methods like first, I lamented the fact that I’d still have to guard that case even though I knew it was never possible and I just wanted to express that to the type system.

If the Array type couldn’t be empty, these methods could return non-optional values, and expressions that use them would be simplified. Empty arrays would use optional chaining to access these methods, and they would their results would be optional, just like today.

Appending

If arrays worked like this, appending to non-empty (now regular) arrays would work as normal. But appending to emptiable arrays would be a mess.

var emptiableArray = //...
emptiableArray == nil 
    ? emptiableArray = [newItem] 
    : emptiableArray?.append(newItem)

This is annoying, but the good news is that as of Swift 3.1, we can specialize specific types of generic extensions. That is, we can add a method to optionals that store concrete array types. (Before, you could only add extensions to specializations that used protocols.)

extension Optional<Array<Element>> {
    func append(_ element: Element) {
        switch self {
        case .some(array):
            array.append(element)
        case .none:
            self = [element]
        }
    }
}

And now we transparently have the behavior that we had before.

Without Loss Of Generality

To take this a step further, what if the type of an array baked in how long it was? For example, adding an element to an Array<of: 4, element: String> would return an Array<of: 5, element: String>. This concept is called dependent types and exists in some experimental languages with more advanced type systems, like Coq, Agda, and Idris. Oisín discusses how we can achieve a similar effect in Swift.

While these are super interesting, they’re also a little bit impractical. If you think about it, it means you can no longer store arrays in a class’s properties, unless you know that that the number of elements in the array won’t change. In a lot of cases, you also won’t know at compile time how many objects are going to come through an API or a database connection.

Simplying making the empty/non-empty distinction has a clear and practical use today, and it cleans up a lot of how Swift looks and works.

NonEmptyArray

This blog post is mostly a thought experiment. But it’s also a regular experiment. To that end, I built a non-empty array type. You can find it on GitHub here. It acts just like an array, but it isn’t emptiable. It conforms to Sequence, Collection, and has == and != methods.

Because of some part of the Swift type system that I don’t fully understand but appreciate nonetheless, you can override methods (like first) from a protocol (like Collection) but change its type from Element? to Element, and Swift will do the right thing at the call-site, and use the more precise type, Element. This means that NonEmptyArray correctly returns non-optional values for first, last, max and min, even though they’re defined on Collection as being Optional. There are tests in the repo asserting this.

Having an array that can’t be empty does interesting things. Methods that insert or append are fine, but methods that remove elements are more problematic. I marked the methods as throws, but after thinking about it more, this may not have been the right call. After all, removing elements from regular Swift arrays can also have deleterious effects, it’s just that they’re allowed to remove one more element than NonEmptyArray can. Swift arrays will fatalError when removing from an empty array, so perhaps that’s the right thing to do here as well.

I’m looking forward to breaking in the NonEmptyArray type in a few projects to see if the clean-up from having non-optional methods like first and friends is worth losing the type sugar that Swift’s built-in array type.

NSCoding requires the NSObjectProtocol, which is a class protocol, and can’t be conformed to by structs. If we have anything we want to encode using NSCoding, the easiest thing do has always been to make it a class, and make it inherit from NSObject.

I’ve found a decent way to wrap a struct in an NSCoding container, and save that without much fuss. I’ll use Coordinate as an example.

struct Coordinate: JSONInitializable {
    let latitude: Double
    let longitude: Double
        
    init(latitude: Double, longitude: Double) {
        self.latitude = latitude
        self.longitude = longitude
    }
}

It’s a simple type, with two scalar properties. Let’s create a class that conforms to NSCoding and wraps a Coordinate.

class EncodableCoordinate: NSObject, NSCoding {
    
    var coordinate: Coordinate?
    
    init(coordinate: Coordinate?) {
        self.coordinate = coordinate
    }
    
    required init?(coder decoder: NSCoder) {
        guard
            let latitude = decoder.decodeObject(forKey: "latitude") as? Double,
            let longitude = decoder.decodeObject(forKey: "longitude") as? Double
            else { return nil }
        coordinate = Coordinate(latitude: latitude, longitude: longitude)
    }
    
    func encode(with encoder: NSCoder) {
        encoder.encode(coordinate?.latitude, forKey: "latitude")
        encoder.encode(coordinate?.longitude, forKey: "longitude")
    }
}

It’s nice to have this logic in another type, which adheres more strictly to the single responsibility principle. An astute reader of the class above can see that the coordinate property of the EncodableCoordinate is Optional, but it doesn’t have to be. We could make our intializer take a non-optional Coordinate (or make it failable), and our init(coder:) method is already failable, and then we would guarantee that we will always have a coordinate if we have an instance of the EncodableCoordinate class.

However, because of a peculiarity in the way NSCoder works, when encoding Double types (and other primitives), they can’t be extracted with decodeObject(forKey:) (which returns an Any?. They have to use their specific corresponding method, which for a Double is decodeDouble(forKey:). Unfortunately, these specific methods don’t return optionals, and they return 0.0 for any keys that are missing or otherwise corrupt. Because of this, I chose to keep the coordinate property as an optional, and encode it as optional, so that I could get objects of type Double? out using decodeObject(forKey:), ensuring a little extra safety.

Now, to encode and decode Coordinate objects, we can create an EncodableCoordinate, and write that to disk with NSKeyedArchiver:

let encodable = EncodableCoordinate(coordinate: coordinate)
let data = NSKeyedArchiver.archiveRootObject(encodable, toFile: somePath)

Having to make this extra object isn’t ideal, and I’d like to work with an object like SKCache from Cache Me If You Can, so if I can formalize the relationship between the encoder and the encoded, maybe I can avoid having to create the NSCoding container manually each time.

To that end, let’s add two protocols:

protocol Encoded {
    associatedtype Encoder: NSCoding
    
    var encoder: Encoder { get }
}

protocol Encodable {
    associatedtype Value
    
    var value: Value? { get }
}

And two conformances for our two types:

extension EncodableCoordinate: Encodable {
    var value: Coordinate? {
        return coordinate
    }
}

extension Coordinate: Encoded {
    var encoder: EncodableCoordinate {
        return EncodableCoordinate(coordinate: self)
    }
}

With these, the type system now knows how to convert back and forth between the types and values of the pair of objects.

class Cache<T: Encoded> where T.Encoder: Encodable, T.Encoder.Value == T {
	//...
}

The SKCache object from that blog post has been upgraded to be generic over some Encoded type, with the constraint that its encoder’s value’s type is itself, which enables bidirectional conversion between the two types.

The last piece of the puzzle is the save and fetch methods for this type. save involves grabbing the encoder (which is the actual NSCoding-conformant object), and saving it to some path:

func save(object: T) {
   NSKeyedArchiver.archiveRootObject(object.encoder, toFile: path)
}

Fetching involves a slight compiler dance. We need to cast the unarchived object to T.Encodable, which is the type of the encoder, and then grab its value, and dynamically cast it back to T.

func fetchObject() -> T? {
    let fetchedEncoder = NSKeyedUnarchiver.unarchiveObject(withFile: storagePath)
    let typedEncoder = fetchedEncoder as? T.Encoder
    return typedEncoder?.value as T?
}

Now, to use the cache, we instantiate one and make it generic over Coordinate:

let cache = Cache<Coordinate>(name: "coordinateCache")

Once we have that, we can transparently save and retrieve coordinate structs:

cache.save(object: coordinate)

Through this technique, we can encode structs through NSCoding, maintain conformance to the single responsibility principle, and enforce type-safety.

Refactoring is continual process. However, this process needs to leave the code in a functional state at frequent intervals. Refactorings that don’t stay functional can’t be deployed regularly, and it’s harder for them to be kept up-to-date with the rest of your team’s code.

Some refactorings are tougher than others, though. The nature of singletons in particular causes them reach their tendrils into many different objects, and this can make them difficult to remove from your project.

Lots of singletons, especially the poorly named ones, have a tendency to accumulate unrelated behaviors, data, and responsibilities, simply because its easier to put them there than anywhere else.

If you want to break up a far-reaching singleton, or if you want to be able to test code that uses that singleton, you have a lot of work to do. You want to slowly replace references to your singleton with smaller, better objects, but you can’t remove the singleton itself until you are completely finished, since other objects rely on it.

Worst of all, you can’t extract a singleton’s behavior and methods into another object, because they’re reliant on the shared state within the singleton. Put another way, if the singleton didn’t have any shared state, you could just make a new instance at each call site and your problem would go away instantly.

So we have a singleton with many disparate responsibilities and a bunch of shared state, being touched from many parts of your app. How can we remove this singleton without actually removing it?

We need a new way to refer to our singleton: a view on the singleton that represents a slice of its many responsibilities, without actually changing the structure of the singleton itself. This slice of behavior and data can be represented with a protocol.

Imagine this kind of singleton in a hypothetical shopping app:

class SessionController {

	static let sharedController: SessionController

	var currentUser: User
	
	var cart: Cart
	
	func addItemToCart(item: Item) { }
	
	var fetchedItems: [Item]
	
	var availableItems: [Item]
	
	func fetchAvailableItems() { }
}

This singleton has at least three responsibilities. We’d love to break it up, but dozens of classes from all over the codebase refer to the properties and functions on this object. If we make a protocol for each “slice” of responsibility, we can start breaking this up.

protocol CurrentUserProvider {
	var currentUser: User { get }
}

protocol CurrentCart {
	var cart: Cart { get }
	
	func addItemToCart(item: Item)
}

protocol ItemFetcher {
	var fetchedItems: [Item] { get }
	
	var availableItems: [Item] { get }
	
	func fetchAvailableItems()
}

The SessionController can conform to these protocols without any extra work:

class SessionController: CurrentUserProvider, CurrentCart, ItemFetcher {
	//...

Because of Swift’s protocol extensions, we can move anything that relies purely on the things provided in the protocol into the extension. For example, availableItems might be any items in the fetchedItems array that has a status of .available. We can move that out of the singleton and into into the specific protocol:

extension ItemFetcher {
	var availableItems: [Item] {
		return fetchedItems.filter({ $0.status == .available })
	}
}

By doing this, we begin the process of slimming down the singleton and extracting irrelevant bits.

Now that we have these protocols, we can begin using them around the app. A fine first step is to extract any usage of the singleton into an instance variable:

class ItemListViewController {
	let sessionController = SessionController.sharedController
	
	//...
}

Next, we can change its type to the type of a specific protocol:

class ItemListViewController {
	let itemFetcher: ItemFetcher = SessionController.sharedController
	
	//...
}

Now, while the class technically still accesses the singleton, it’s done in a very limited way, and it’s clear that this class should only be using the ItemFetcher slice of the singleton. We’re not done, however. The next step is intialize this class with an ItemFetcher:

let itemFetcher: ItemFetcher

init(itemFetcher: ItemFetcher) {
    self.itemFetcher = itemFetcher
    super.init(nibName: nil, bundle: nil)
}

Now, the class has no idea what kind of ItemFetcher it was intialized with. It could be the singleton, but it could also some other type! This is called dependency injection. It lets us inject alternate dependencies into our view controllers and other objects, which will let us test these objects more easily. The places where this view controller is initialized across the app have to be updated to use this new intializer.

Ideally, view controller initalization is only done inside of Coordinators, which should simplify how much you need to pass those singletons around. If you don’t use coordinators, any dependency that the fourth view controller in a navigation controller might need has to be passed through the first, second, and third view controllers as well. This is not ideal.

Now, this is the hard part: this process has to be repeated across every reference to this singleton across your app. It’s a tedious process, but it’s mostly rote work, once you’ve figured out what the various responsibilities and protocols are. (One tip: if you have a CurrentUserProvider, you might want a separate MutableCurrentUserProvider. The objects that only need to read from the current user don’t need to have access to write to that storage as well.)

Once you’ve changed all your references to your singleton, you’ve removed a lot of its teeth. You can remove its static singleton accessor property, and then view controllers and other objects will only be able to play with the objects that they are passed.

From here, you have a few options. You can now easily actually break up the singleton itself into all of the little responsibilities that you’ve created.

  • You can make ItemFetcher a class instead of a protocol, and move all the code from SessionController into the new ItemFetcher class, and pass the class around instead of the singleton.
  • You can keep ItemFetcher as a protocol, and make a class called ConcreteItemFetcher, and move the singleton code into this new class. This solution gives you a few more options, since you can inject other objects that conform to the ItemFetcher protocol, suitable for unit testing, screenshot testing, demoing the app, and other purposes. This is a little more work, but it also has more flexibility.

By creating “slices” of responsibility on top of your singletons, you can break them up into their constitutive responsibilities without changing the structure of the singleton itself. From there, you can use dependency injection to give objects only those things that you expect them to use. Finally, you can make your singletons no longer have singleton accessors, and ride off into the glorious sunset of well-factored code.

Back in the heady days of iOS 2, before NSURLSession, developers had to build their own networking stack. There was a class called NSURLConnection and it had a delegate, the aptly-named NSURLConnectionDelegate.

An object conformed to NSURLConnectionDelegate with a few key methods:

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data;
- (void)connectionDidFinishLoading:(NSURLConnection *)connection;
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error;

While the new NSURLSession APIs are much nicer, these methods gave you a lot of control (mostly control that you didn’t need). They have another quality that I think is somewhat enlightening. This protocol suggests its own implementation.

You can tell by looking at the API that didReceiveResponse will get called once, didReceiveData will get called at least once and maybe even more than once, and connectionDidFinishLoading will get called once as well. didFailWithError might get called once, and you probably won’t get any more callbacks after that one. And since you know that you’re going to have to keep track of some NSMutableData instance variable to glue all of these disparate pieces of data together. With that knowledge, you can put together an implementation:

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
	self.receivedData = [NSMutableData data];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
	[self.receivedData appendData:data];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
	id object = [NSJSONSerialization JSONObjectWithData:self.receivedData options:0 error:nil];
	//call completion block or delegate
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
	self.error = error
	//call completion block or delegate
}

(This code is actually from an old app of mine, from around 2011.)

Because you need to keep track of this instance variable, it’s glaringly obvious that you can’t keep it around in a view controller or another high-level object. Every single request that a view controller needed to send would need its own NSMutableData variable. So just by the nature of the design of this API, it almost forces you to create a new object for a request. (This is a pit of success. Make the right way and the easy way line up with each other.)

And so even those of us who were writing huge view controllers knew that it was wrong to keep that kind of data in a view controller, so we made a custom little object for interfacing with a web server. Sometimes that custom object got out of hand and started doing way too much, but that’s a blog post for another day.

Eventually, we all moved on to AFNetworking, which handled all those messy bits for you. But somewhere, deep in the bowels of AFNetworking, there was an object whose primary purpose was to act as this delegate.

While there’s plenty more I could say about the institutional reasons that caused Apple gave us this low-level API instead of something a little simpler to use, I’ve always been more intrigued by the idea of a protocol that gently forces you to create a new object, just by the virtue of its API. What if more protocols pushed you in that direction? What if we took existing protocols and forced ourselves to implement them as wholly new objects?

I want to examine three of these cases.

First, UITableViewDataSource. This is a really common protocol to break out of a view controller. This extraction is a frustrating one, because the table view protocols are somewhat poorly factored. Why is cell height calculation in UITableViewDelegate, whereas cell generation (like cellForRowAtIndexPath:) is in UITableViewDataSource?

Still, it can be a worthwhile object to extract, but remember that the object conforming to this protocol probably should have its own collaborators and child objects.

Second, I want to take a look at UIAlertViewDelegate. Because UIAlertView has been deprecated in favor of UIAlertController, which has a block-based API, this protocol isn’t common anymore. However, we can still learn from it. The protocol suggests making an object whose job it is to present the alert, conform to its delegate, and handle the button taps. Even though the new block-based API doesn’t suggest this implementation in the same way as the protocol-based API did, it’s a smart place to start thinking about breaking out a responsibility. I proposed this in 8 Patterns to Destroy Massive View Controller, as the “Interaction” pattern.

Lastly, I want to talk about UINavigationControllerDelegate. This delegate is a weird one, and I struggled for a long time with this one. Because UINavigationController objects don’t really have a parent, it’s not obvious who should be their delegate. Most of the work they do (pushing and popping) is usually handled by their child view controllers. If a second child view controller in the stack needed access to the delegate of the navigation controller, it could just call self.navigationController.delegate = self in viewDidLoad, and that would work. But then if the third view controller in the stack also needed access to that information, it would take that delegateness away from the second view controller, and the second view controller wouldn’t work as expected anymore.

Traditional navigation-based iOS development has an upside-down view of the app’s control hierarchy. The child (a view controller) grabs hold of the parent (the navigation controller) and tells it how to behave. With the navigation controller having no logical parent, its delegate doesn’t naturally fit in anywhere.

The solution to both of these problems took some time for me to figure out, but it ended up being the kernel of the idea of Coordinators. Coordinators are an object suggested by the idea of a specialized object for a UINavigationControllerDelegate, and as the natural parent for a UINavigationController are the right place for those delegate methods to get fired.

Every object needs a purpose, and conforming to a complex delegate can be one purpose. Next time you see a delegate, ask yourself if it makes sense for this delegate to be its own object. Break it out, and see if you like it.

Swift is a successor to Objective-C only because it has the same vendor. It doesn’t look the same, doesn’t act the same, and doesn’t feel the same. Paradigms that worked great in Objective-C, like method names, are slowly being updated for a bright new Swift world. For example, in Objective-C, this method was called with its full form:

[string dataUsingEncoding:NSUTF8StringEncoding];

In Swift 2.2, it was somewhat ungainly:

string.dataUsingEncoding(NSUTF8StringEncoding)

In Swift 3, the method became much more streamlined:

string.data(using: .utf8)

The Swift 3 version of this method is right for Swift, in the same way that the Objective-C version was right for Objective-C. I think this article does a good job covering how to update your own method names for this new world.

There are other parts of the frameworks and the idioms that we use to write our apps that also need to be updated in for a Swiftier world. Today, I’d like to focus on delegate naming.

Delegates in Swift don’t translate very well from Objective-C. Objective-C was very much about “senders” and “receivers”. Much of Apple’s Objective-C documentation is written in these terms. For example, the method isFirstResponder on UIResponder has documentation that reads:

Returns a Boolean value indicating whether the receiver is the first responder.

And of course, when setting up a target-action selector, the idiomatic name for the first argument has historically been sender:

- (void)buttonTapped:(UIButton *)sender {

Delegates work much the same way: the first argument for a delegate method in Objective-C has always been the sender. You can see why this is useful: if you (the receiver) are the delegate of multiple objects of the same type, you’ll need a way to differentiate them. The delegate provides you with the first parameter, and you can switch on it.

I’m going to use some examples from the Backchannel SDK with some class names simplified for brevity.

There are two main types of delegate methods. First, those that just indicate that an event happened.

- (void)messageFormDidTapCancel:(BAKMessageForm *)messageForm;

In Swift, this translates to:

func messageFormDidTapCancel(_ messageForm: BAKMessageForm)

This doesn’t look right in Swift 3 anymore. In Swift 3, redundancy is eliminated (the two messageForm names), and first arguments should generally be named rather than removed using the underscore.

The second type of delegate method indicates that an event happened and includes some data. I want to look at two examples of this one.

- (void)messageForm:(BAKMessageForm *)messageForm didTapPostWithDraft:(BAKDraft *)draft;
- (void)messageForm:(BAKMessageForm *)messageForm didTapAttachment:(BAKAttachment *)attachment;

In Swift, these translate to:

func messageForm(_ messageForm: BAKMessageForm, didTapPostWithDraft draft: BAKDraft)
func messageForm(_ messageForm: BAKMessageForm, didTapAttachment attachment: BAKAttachment)

These are horrible. Why are both of these methods called messageForm? Also, starting a method with a noun here doesn’t make sense: it usually suggests that you’ll be returning an object of that type (think about data(using:) on NSString, which returns a Data). We’re not returning any message form objects here. That “message form” is actually the name of the first parameter. These are very confusing method names!

Both of these types of delegate methods can be fixed by moving the “sender” to the back of the line, and bringing the verbs forward. For the first one, the event that the sender is informing the delegate about is didTapCancel, instead of messageFormDidTapCancel. Let’s start with that:

func didTapCancel(messageForm: BAKMessageForm)

This is already much better. The action is brought to the front, and becomes the name of the method, and it’s a lot clearer what this method does. I think we could use a preposition instead for the parameter name, to make it read a little nicer at the call site:

func didTapCancel(on messageForm: BAKMessageForm)

I haven’t found a hard and fast rule for which preposition to use yet. I’ve found “on”, “for”, “with”, and “in” to all be useful in different circumstances. Users tap “on” a form, so I think “on” is appropriate here.

Let’s also take a look at delegate methods that have data to pass back. Bringing the verb to the front helps, and switching to a preposition for the delegate name also cleans up these types of methods. Instead of:

func messageForm(_ messageForm: BAKMessageForm, didTapPostWithDraft draft: BAKDraft)

we have the much Swiftier:

func didTapPost(with draft: BAKDraft, on messageForm: BAKMessageForm)

and

func didTap(attachment: BAKAttachment, on messageForm: BAKMessageForm)

These rules aren’t endorsed by anyone except for me, but I think they make much more sense than the current rules by which we write delegate methods. Going forward, I’ll probably start writing my Swift delegate methods with this structure.

I’ll leave you with some UITableView delegate and data source methods and what they could look like in this awesome future:

func numberOfSections(in tableView: UITableView) -> Int

numberOfSections follows this scheme and looks pretty good already.

These methods, however, don’t look so great:

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)

Here they are with a little love:

func numberOfRows(inSection section: Int, in tableView: UITableView) -> Int
func cellForRow(at indexPath: IndexPath, in tableView: UITableView) -> UITableViewCell
func didSelectRow(at indexPath: IndexPath, in tableView: UITableView)

A few weeks ago, Matt Gallagher wrote about Swift’s error model, in comparison with the Result type. He puts it quite succinctly:

Swift’s error handling has a major limitation: it can only be used to pass an error to an enclosing catch scope or the previous function on the stack.

If you want to handle errors across asynchronous boundaries or store value/error results for later processing, then Swift error handling won’t help.

This is the clearest explanation of the problem with Swift’s error handling that I’ve seen. Having a dedicated Result type, Matt argues, would solve the async problem and the error storage problem. John McCall, on the mailing list, wrote about why the team didn’t include Result:

We considered it, had some specifics worked out, and then decided to put it on hold. Part of our reasoning was that it seemed more like an implementation detail of the async / CPS-conversion features we’d like to provide than an independently valuable feature, given that we don’t want to encourage people to write library interfaces using functional-style error handling instead of throws.

The Swift team considers Result not useful enough to include in the standard library. The only reason to add it, they argue, is as an implementation detail of async features that they would add in the future.

Let’s examine what those potential async features might look like, design them in the same way that the error handling was designed, and see how these new features could fill all the gaps of the current error handling model.

If we use C#’s async/await model that I discussed in the last post, a Swifty version might look something like this:

async func getCurrentUsersFollowers() throws -> [User] {
	let user = try await APIClient.getCurrentUser()
	let followers = try await APIClient.getFollowers(for: user)
	return followers
}

This is the closest I can get it to how the error model works. In the same way that Swift’s throwing functions don’t return a Result, this function doesn’t return an Async<[User]> or any kind of wrapped type (e.g, Task<[User]>, à la C#), but rather the raw value itself, and it uses the async decorator on the function (like the throws decorator) to express that the function must be awaited upon.

func updateUI() {
	do {
		self.followers = try await getCurrentUsersFollowers()
		self.tableView.reloadData()
	} catch let error as APIError {
		self.presentError(error)
	} catch error {
		print(error)
	}
}

To use getCurrentUsersFollowers(), we need a function that returns Void, so that it won’t need to be marked as async. This is the equivalent of wrapping function marked throws in do/catch blocks.

Lastly, we need some way to define a new async task. The Swift error model uses the throw keyword opposite the return keyword to handle the distinction between success and failure. I’m not sure how exactly Swift syntax would define a new async task, but for simplicity’s sake, let’s imagine it as a closure that runs on some background thread. When the closure is complete, it returns a value, and that’s the result of the async function:

async func getCurrentUser() {
	let url = buildURLForCurrentUser()
	return await {
		let data = Data(contentsOf: url)
		let user = //parse JSON, construct User
		return user
	}
}

This is some super fake syntax I made up. The goal is to stay as true to the model of Swift’s error handling as possible. Specifically, I want to prevent users from constructing a type that would represent the async task, in the same way you don’t create a Result when using the error handling constructs.

Since we don’t have a type to work with, we can’t do anything other than perform a sequential series of asynchronous, potentially erroring tasks, such as in the getCurrentUsersFollowers() function. I’m happy to grant that sequential, erroring tasks are 90% of the kind of work that we do with asynchronicity, in the same way that passing errors up the stack is 90% of what we need error handling for. But the remaining 10% of stuff is important too. As Larry Wall says, “make the easy jobs easy, without making the hard jobs impossible”. Swift’s error handling and this new, fake async syntax both make the hard jobs literally inexpressible, requiring programmers to pull in their own abstractions, like Result and Promise, to get the job done.

Promise.all is probably the second most common use case for async tasks: given an array of async tasks, create one async task that completes when every subtask has completed. If we wanted to implement Promise.all with this new async syntax we’d need some combination of an array of functions that are async, a concurrent dispatch queue, a dispatch group, and a bunch of messy synchronization. On the other hand, its implementation on Promise almost trivial, complete with thread-safety and type-safety.

Other, more infrequently-used behaviors, like recover, delay, or race, are similarly easy with Promises, but tougher with this kind of async feature. Here’s another one that I found useful, Promise.zip:

public static func zip<T, U>(first: Promise<T>, second: Promise<U>) -> Promise<(T, U)> {
    return Promise<(T, U)>(work: { fulfill, reject in
        let resolver: (Any) -> () = { _ in
            if let firstValue = first.value, secondValue = second.value {
                fulfill((firstValue, secondValue))
            }
        }
        first.then(resolver, reject)
        second.then(resolver, reject)
    })
}

Where Promise.all requires that every promise have the same type, Promise.zip (and any higher arity versions of it you might want) combines two promises with two different types (T and U) into one promise of type (T, U) as a tuple. This way, if you need two things to finish that return different types, you can maintain their types while still waiting for them to both complete. Promise.all is used frequently, and there will almost definitely be some kind of facility for it built into Swift’s async features (even if they’re hard-coded into the syntax). Promise.zip, on the other hand, would hardly ever be used, so the odds of it being added to the standard library are nil. But if one of our projects eventually did need it, it’s nice to know it’s easy enough to add ourselves.

As easy as it is to write helpers on a fully-fledged abstraction like Promise, it’s tricky and complicated when the feature is built into the language’s syntax. Without the manipulability of fully-blown types that represent these constructs, we can’t build useful one-off functions like zip.

Consider if optionality were built into the language the way that errors are. You could never extend the Optional type. There’d be no more using flatMap to unwrap. There’d be no way to turn a tuple with two optionals into one optional tuple with two non-optional values (the equivalent of our Promise.zip above). My fake async/await syntax and the very real Swift 2 error handling are hard-coded into the language, and they both prevent this kind of extensibility and flexibilty that you get with Optional.

This extensibility is often limited and even removed with excuses of safety and soundness; we’ve certainly seen those arguments made for removing features like mutability, metaprogramming, and reflection. However, in many of these cases, these features are restricted without any increase in type safety or the other guarantees that we subscribe to Swift for. In those cases, the reasoning for why we can’t have nice things falls apart. As I wrote a few weeks ago:

Being able to conform my own types SequenceType shows that the language trusts me to make my own useful abstractions (with no loss of safety or strictness!) on the same level as its own standard library.

Perhaps I’m wrong about how the syntax will look. I truly hope that’s the case. As I’ve shown, this syntax is purposely almost crippled in order to make two points: first, that without the proper supporting abstractions, async/await develops holes very similar to the current error handling model. The Swift team wants to fill in one of those holes (async) with more syntax, but that merely kicks the can down the road.

Second, the goal of this fictional async/await syntax was to design it so that it’s limited in similar ways to the error handling model; given these limitations, if async/await sans abstractions falls short, then doesn’t our current error model also deserve an overhaul?

I don’t know if the ship has sailed for redesigning the way that Swift error handling works; it probably has. The async ship is still in the docks, to stretch the metaphor, and I’d like to make sure the language that we’ll be writing code in for the next 20 years has as solid of a foundation as possible.