Make Money Outside the Mac App Store book cover

My book is out: Make Money Outside the Mac App Store.

Own your products and know your customers: sell outside the Mac App Store. In a few hours, you’ll have in-app purchases, a trial mode, and piracy protection all set. The book includes fully functional sample projects and code to ready to be copied into your app.

Replacing Loops with Mapped Ranges

During the last weeks, I tried to use map() even when the conversion wasn’t straightforward to learn how it affects reading code. I found that some applications of map() were dumb while I liked how others turned out to read. The functional programming paradigm is about writing code in a declarative way, which has its benefits.

Take this, for example:

extension Int {    
    func times<T>(f: () -> T) -> [T] {
        var result = [T]()
        
        for _ in 0..<self {
            result.append(f())
        }
        
        return result
    }
}

10.times { "foo" }
// => ["foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo"]

Looping over the range works well and is the way of the future to use for-loops from A to B, but a few months ago I thought this was clever already.

The method has 3 parts:

  1. Declare a mutable array
  2. Use (mutate) the array
  3. Return the array

When I see mutable arrays used like this, I see map, though:

extension Int {    
    func times<T>(f: () -> T) -> [T] {
        return (0..<self).map { _ in f() }
    }
}

The result is a bit more terse. But unlike the mutable array from above, you do not wonder what will happen to the array, why it is mutable (var instead of let) etc. Instead, you see that there’s a range and that each element in the sequence is transformed (“mapped”) to something else.

The return (0..<self).map part already tells most of the story: you can expect an array with as many elements as self indicates. To guess what the contents will look like, you’ll have to take a look at the block.

Compared this to the example from above. There, you knew an array is involved. Then there was a loop. Then the array was changed with every iteration. You had to read 3/4 of the method body to fathom what the result will be.

I am afraid to go too far down the rabbit hole of functional thinking, thus rendering my code harder to comprehend. This example is not that bad I think. But when I prefer mapping the N elements in a range to produce an array of size N, I think I already lost some people in my team. What’s idiomatic Swift and thus to be expected from co-workers and what’s too much?

Type-Safe Storyboard Segues

I thought I had my share of Storyboard Segue-related tips already to make them less brittle when I found yet another approach to use Swift’s enums for segues by Ricardo Pereira.

His team uses enums not for identifiers but to associate model data with the segues:

enum StoryboardDestination {  
    case Login
    case DeviceGroups(userAuth: UserAuthentication)
    case Devices(userAuth: UserAuthentication, model: DeviceGroup)
}

These have to be translated to Strings in order to programmatically perform a segue. You can only either have associated values in enum cases or make a segue identifier enum inherit from String, but not both, sadly. Somewhere you’ll have to place manual translation to String. For their app Qold, they did it in an extension:

extension UIViewController {

    func performSegueWithIdentifier(destination: StoryboardDestination) {
        let segue: String

        switch destination {
        case .Login:
            segue = "LoginSegue"
        case .DeviceGroups(_):
            segue = "DeviceGroupsSegue"
        case .Devices(_, _):
            segue = "DeviceGroupDetailsSegue"
        }

        performSegueWithIdentifier(segue, sender: Box(destination))
    }
}

The method name should’ve simple been performSegue(destination:), but hey.

The enum value gets boxed and then becomes the sender of that command. In prepareForSegue, you can unbox it and use the associated values as model data for the destination view controller.

With segues in general, I never liked that the source view controller is supposed to configure the destination view controller. The destination view controller thus gets pushed around. Maybe not much, but it’s not my favorite thing to do. I like to be polite to objects.

Ricardo got me hooked when he shows how they handle the configuration: the destination view controller has to conform to StoryboardDependencies to configure itself in assignDependencies:

class StoryboardViewController: UIViewController {

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

        // ...
        if let destinationViewController = anyDestination as? StoryboardDependencies,
            let dependencies = sender as? Box<StoryboardDestination> {
                destinationViewController.assignDependencies(dependencies)
        }
    }
}

Even “configure” would’ve been a better choice for a method name than “assign dependencies” from the destination view controller’s point of view (which is the one that counts). The destination view controller actually takes (not assigns) the dependencies:

class DevicesViewController: StoryboardViewController, StoryboardDependencies {

    func assignDependencies(dependencies: Box<StoryboardDestination>) {
        switch dependencies.value {
        case .Devices(let userAuth, let model):
            self.userAuth = userAuth
            deviceGroup = DeviceGroupViewModel(model)
        default:
            break
        }
    }
}

Otherwise, this approach looks solid to me.

I don’t know why the boxed value is transmitted, though; having to use a Box type in some cases in unfortunate but necessary. Nevertheless this is a code smell. I wouldn’t want to propagate this too far in my app and unbox in StoryboardViewController.prepareForSegue(_:) already. All of these are minor issues and can be remedied easily in my own code.

Making the convenience method work in other view controller subclasses

StoryboardViewController encapsulates supporting different kinds of segue configurations. This is great because if you stick to using the StoryboardDestination enum, everything in terms of segue setup now comes for free.

But only if you have view controllers subclass StoryboardViewController. If you inherit from a UITableViewController, you’re out of luck at first.

Thanks to protocol extensions, we can remedy this at least a bit.

protocol PreparesSegues {
    func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
}

extension PreparesSegues {
    func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        // code from StoryboardViewController
    }
}

This is a typical example of using protocols as mixins: you can remove StoryboardViewController and extend any view controller subclass with this protocol to get the convenient version of prepareForSegue(_:, sender:) for free again.

Productivity Tips for Programmer Solopreneurs

Vikas Thakur is an INTP personality type – very common among programmers I’d say. He wasn’t good at micro managing himself until he found the tools to prevent bad habits (casually browsing the web) and track his progress to gather intelligence about how he works. He found 5 tools and 5 habits to do the trick (among them my Word Counter).

If you suffer from unwillingly checking your Twitter feed, have a look at his tips. There may be something for you, too. My flat mate un-learned wasting time on YouTube and Facebook with a tool last year. I recommend you give it a try and see for yourself if that sounds like you.

The Power of Guard

Here’s a guard statement with many different kinds of features by Benedikt Terhechte:

guard let messageids = overview.headers["message-id"],
    messageid = messageids.first,
    case .MessageId(_, let msgid) = messageid
    where msgid == self.originalMessageID
    else { return print("Unknown Message-ID:", overview) }

I love guard statements. It helps make code much more readable and keep methods un-intended.

I feel less amorous about guard-case and if-case matching, though:

if case .Fruit = foodType { ... }

This reads an awful lot like Yoda conditions where you place the constant portion on the left side. This isn’t even a typical boolean test (which would use the equality operator ==) but a failable assignment (=). I can force myself to read and write it this way, but it always feels backward to me. It took me quite a while to memorize this, which I found surprising, as it was comparatively easy to learn Swift in the first place.

Apart from the guard-case portion, the example contains your standard guard-let unwrapping. The else clause is special though, and I didn’t know this would work:

guard someCondition else { return print("a problem") }

When the function is of return type Void, you can return a call to another void function. This is shorter than splitting these two instructions on two lines, but it’s too clever for every reader to understand. print("a problem"); return is just as compact, as Terhechte points out.

How to Edit NSTableView Headers with a Double-Click

When you work with view-based NSTableViews, cells by default contain a NSTextField. You can edit cell contents with them. The headers are not designed to be edited, though. You don’t have much control over the column headings from Interface Builder. So you have to build this yourself.

I assembled an example project for this for your convenience. Find it on GitHub.

screencast
The result: it ends editing on enter, tab, and when double-clicking another cell

Edit on double-click

NSTableView conveniently supports setting a doubleAction in Interface Builder. From that @IBAction, you can find out if the header row was clicked like so:

@IBAction func tableViewDoubleClick(sender: TableView) {

    let column = sender.clickedColumn
    let row = sender.clickedRow

    // Abort when clicked outside the table bounds
    guard column > -1 else { return }

    if row == -1 {
        editColumnHeader(tableView: sender, column: column)
        return
    }

    editCell(tableView: sender, column: column, row: row)
}

private func editColumnHeader(tableView tableView: TableView, column: Int) {
    // We'll get to this in a second
}

private func editCell(tableView tableView: TableView, column: Int, row: Int) {

    guard row > -1 && column > -1
        let view = tableView.viewAtColumn(column, row: row, makeIfNecessary: true) as? NSTableCellView
        else { return }
        
    view.textField?.selectText(self)
}

NSTableCellViews have text fields and can be edited easily. Header cells don’t work this way, so we have to figure that out ourselves.

Overlaying header cells with the field editor

I didn’t know about the notion of a per-window “field editor” before, but this was the key to make editing header cells possible.

In short, each window has a reusable NSTextView that is displayed in each and every editable text component. This is called the field editor. When you double click a cell in your table, the field editor visually moves inside the cell’s boundaries. When you tab your way through the table, the field editor moves around.

This means that not the visible table cells are edited but an overlay text view. When the field editor is shown, the underlying cell doesn’t change. It’s invisible because the field editor visually hides it behinds itself. If you type something, the field editor takes the text; the cell still doesn’t change. Only when the field editor closes will the cell obtain its new value. Orchestrated properly, all of this is invisible to the user.

We will use the field editor to achieve the same effect since the table header view doesn’t support all of this convenience itself.

You can request the field editor from your NSWindow instance anytime:

let targetView: NSView = // ...
let createIfNecessary = true
let fieldEditor = self.window?.fieldEditor(createIfNecessary, forObject: targetView)

Using the field editor afterwards takes care of setting the frame correctly. An NSCell implements selectWithFrame(_:, inView:, editor:, delegate: , start:, length:) to configure the field editor you pass as the editor argument properly, selecting length characters of the cell’s text beginning at start.

Making the header cell editable

I encapsulated calling this method in a custom NSTableHeaderCell subclass. The header cell becomes the NSTextViewDelegate, too, to take the new value when the field editor goes away:

class TableHeaderCell: NSTableHeaderCell, NSTextViewDelegate {

    func edit(fieldEditor fieldEditor: NSText, frame: NSRect, headerView: NSView) {

        let endOfText = (self.stringValue as NSString).length
        self.highlighted = true
        self.selectWithFrame(frame,
            inView: headerView,
            editor: fieldEditor,
            delegate: self,
            start: endOfText,
            length: 0)

        // Resetting the style of the field editor to match the header
        fieldEditor.backgroundColor = NSColor.whiteColor()
        fieldEditor.drawsBackground = true
    }

    func textDidEndEditing(notification: NSNotification) {

        guard let editor = notification.object as? NSText else { return }

        self.title = editor.string ?? ""
        self.highlighted = false
        self.endEditing(editor)
    }
}

This setup places the cursor at the end of the text box instead of selecting the existing content. When the field editor resigns first responder, for example because the user hits the enter key, textDidEndEditing(_:) is invoked.

The editColumnHeader method I left out at the beginning can now be written as follows:

extension TableWindowController {
    private func editColumnHeader(tableView tableView: NSTableView, column: Int) {

        guard column > -1,
            let tableColumn = tableView.tableColumn(column: column),
            headerView = tableView.headerView as? NSTableHeaderView,
            headerCell = tableColumn.headerCell as? TableHeaderCell,
            fieldEditor = fieldEditor(object: headerView)
            else { return }

        headerCell.edit(
            fieldEditor: fieldEditor,
            frame: headerView.headerRectOfColumn(column),
            headerView: headerView)
    }
}

Adopt the value the user enters

This will work as expected and set the TableHeaderCell’s text to the field editor’s value if you hit enter or tab.

But there’s a common problem: the header doesn’t obtain the changed text if you double-click out of the field editor to edit another column heading or a cell. That’s because the field editor doesn’t lose focus in these cases and doesn’t fire textDidEndEditing. The field editor is never destroyed; and when you edit another cell, you merely change its contents and draw it in another place.

There are various suggestions about how to trigger the textDidEndEditing event nevertheless. I found a very easy trigger: when a new field editor is requested. That’s exactly when the existing field editor may change positions.

First, support a manual reset in a custom field editor:

class HeaderFieldEditor: NSTextView {

    static let ManualEndEditing = "field editor will change"

    func switchEditingTarget() {

        guard let delegate = self.delegate else { return }

        let notification = NSNotification(name: HeaderFieldEditor.ManualEndEditing, object: self)
        delegate.textDidEndEditing?(notification)
    }
}

I could (or should?) fire a proper NSTextDidEndEditingNotification to indicate the text field loses focus, too, but I don’t need that in my app (I’m not observing anything on my own and rely on the delegate method) and I worry about unintended side-effects. Keep in mind that textDidEndEditing is only a convenience mechanism we exploit here.

We can call this method when a field editor is requested. The window has a default field editor. To use our own, we can use its NSWindowDelegate’s windowWillReturnFieldEditor(_:, toObject:) method and return a custom object instead.

Since a field editor is requested for every cell when the table is displayed, we will limit the use of the custom field editor to table header views:

class TableWindowController: NSWindowContoller {
    // ...
    
    lazy var headerFieldEditor: HeaderFieldEditor = {
        let editor = HeaderFieldEditor()
        editor.fieldEditor = true
        return editor
    }()
}

extension TableWindowController: NSWindowDelegate {
    
    func windowWillReturnFieldEditor(sender: NSWindow, toObject client: AnyObject?) -> AnyObject? {

        // Return default field editor for everything not in the header.
        guard client is TableHeaderView else { return nil }

        headerFieldEditor.switchEditingTarget()

        return headerFieldEditor
    }
}

This in combination with the regular textDidEndEditing event suffices.

Making the result pretty

The field editor will be too high by default. I tried a few values and came up with a hacky but working solution, hard-coding the frame change values in a header view subclass. I found 4pt vertical padding to do the trick and show the field editor right above the header cell:

class TableHeaderView: NSTableHeaderView {

    /// Trial and error result of the text frame that fits.
    struct Padding {
        static let Vertical: CGFloat = 4
        static let Right: CGFloat = 1
    }

    /// By default, the field editor will be very high and thus look weird.
    /// This scales the header rect down a bit so the field editor is put
    /// truly in place.
    func paddedHeaderRect(column column: Int) -> NSRect {

        let paddedVertical = CGRectInset(self.headerRectOfColumn(column), 0, Padding.Vertical)
        let paddedRight = CGRect(
            origin: paddedVertical.origin,
            size: CGSize(width: paddedVertical.width - Padding.Right, height: paddedVertical.height))

        return paddedRight
    }
}

Using this in the double click handler:

private func editColumnHeader(tableView tableView: NSTableView, column: Int) {

    guard column > -1,
        let tableColumn = tableView.tableColumn(column: column),
        headerView = tableView.headerView as? TableHeaderView,
        headerCell = tableColumn.headerCell as? TableHeaderCell,
        fieldEditor = fieldEditor(object: headerView)
        else { return }

    headerCell.edit(
        fieldEditor: fieldEditor,
        frame: headerView.paddedHeaderRect(column: column),
        headerView: headerView)
}

Conclusion

There’s one caveat I didn’t yet solve: when switchEditingTarget is called, during textDidEndEditing, the header cell will call endEditing(_:) to end the editing session – thereby triggering a NSTextDidEndEditingNotification which calls the textDidEndEditing method again.

Update: Found something. Just call endEditing manually:

class HeaderFieldEditor: NSTextView {

    func switchEditingTarget() {

        guard let cell = self.delegate as? NSCell else { return }

        cell.endEditing(self)
    }
}

That solves the issue.

Another thing that’s missing in the sample: tabbing through the header cells. You can double-click to edit them, but hitting tab will only end the editing session. I suppose you have to fire a different event when tab is pressed and select the next header from the view controller.

Look at the sample project on GitHub and play with it yourself.

Refactoring to Clean Value Transformations in Swift

Daniel Steinberg’s presentation “Ready for the Future: Writing Better Swift” teaches us a lot about readable code. He refactors a calculation into many functions with very specific responsibilities. The resulting functions are super slim.

The result is this:

let lastWeeksRevenues = lastWeeksSales
                        » anArrayOfDailySales
                        » replaceNagiveSalesWithZeroSales
                        » calculateRevenuesFromSales

When you read that code it should be very clear what’s going on. The function names communicate their intent.

Now the implementation:

func anArrayOfDailySales(rawSales: AppSales) -> [Int] {
    return rawSales.map{$0}
}

func replaceNagiveSalesWithZeroSales(sales: [Int]) -> [Int] {
    return sales.map(negativeNumbersToZero)
}

func negativeNumbersToZero(number: Int) -> Int {
    return max(0, number)
}
    
func calculateRevenuesFromSales(sales: [Int]) -> [USDollars] {
    return sales.map(revenuesInDollarsForCopiesSold)
}

func revenuesInDollarsForCopiesSold(numberOfCopies: Int) -> USDollars {
    return numberOfCopies
        » revenuesForCopiesSold
        » toTheNearestPenny
}

let unitPrice = 1.99
let sellersPercentage = 0.70

func revenuesForCopiesSold(numberOfCopies: Int) -> USDollars {
    return Double(numberOfCopies) * unitPrice * sellersPercentage
}

infix operator » {associativity left}

func »<T, U>(input: T, transform: T -> U) -> U {
    return transform(input)         
}

Apart from the » operator which merely changes foo.map(bar) to foo » bar, the functions are very small, easy to read. This reminds me of the result of 3/4 of Sandi Metz’s arbitrary rules for writing Ruby code:

  1. Classes must be shorter than 100 lines
  2. Methods must be shorter than 5 lines
  3. Always pass less than 4 parameters into a method

Of course the result is a lot of functions for a rather simple algorithm. But it works well because it is easy to read in the long term. Even newcomers can grasp what’s going on without knowing much about the language or typical Cocoa-programmer conventions.

Bonus: you can unit test each function to check if the parts of the overall algorithm works as expected.

Use Xcode Deprecation Warnings to Refactor

A refactoring in a side project requires finding places where a property we want to get rid of is currently used.

Finding the property name in the project will not work very well because other types use a similar named property. We only want to remove Banana.size, but not Jeans.size.

Deprecations to the rescue:

class Banana {
    
    @available(*, deprecated=1.0)
    let size: Int
}

It’s even possible to provide instructions to co-workers:

@available(*, deprecated=1.0, message="Replace with the new Canana")
class Banana { ... }

Now Xcode will point out where we have to go to get rid of things and change logic. We can have a look at all of the places and perform changes so the existing code does compile (and test!) at all times – only when no deprecation warnings show up anymore will we remove the property.

Xcode warnings
Deprecation warnings in Xcode

The benefit of being able to compile at all times during the process is huge compared to removing the offending stuff right now and fixing compiler errors later.

Currying and Treating Instance Methods as Curried Functions

Currying is a very useful and interesting thing. It means that you can write functions in parts. If you don’t provide all parts at once, you won’t get the “real” result but a closure that accepts the missing parameters.

Like this, with spacing added to reveal how the nested closure maps to the chain of return types:

func add(a: Int) -> (Int)    -> Int {
    return {        (b: Int) -> Int in
        return a + b
    }
}

print(add(31)(13)) // => 44

So you can break the parameter list up and call the result of the first function call again. This is useful for storing partial applications:

let add5 = add(5)
print(add5(10))    // => 15
print(add5(20))    // => 25

This is turn can be useful to provide context for setting up a block to be called later. You provide the parameters you know in advance and leave some out to be called later.

class Server {
    func fetchData(completion: (data: NSData?) -> Void) {
        //...
        completion(result)
    }
}

This method expects a block or function of type NSData -> Void. Here’s a curried function that does not fit unless you provide the first set of parameters:

func showDataInViewController(viewController: ServerDataViewController) -> (NSData?) -> Void {
    return { data in 
        // This closure captures `viewController`, too.
        guard let data = data else { return }
        viewController.showData(data)
    }
}

Now I here’s a contrived example to show how you can vary one part of that function call while leaving the other unspecified

if someInitialCondition {    
    server.fetchData(showDataInViewController(initialViewController))
} else {
    server.fetchData(showDataInViewController(historyViewController))
}

You see:

  • showDataInViewController(foo) is of type (NSData) -> Void, while
  • showDataInViewController is of type (ServerDataViewController) -> (NSData?) -> Void.

If all this is super new to you: you can reference any function or method instead of calling it, like so:

// Reference print(...)
let logger = print

// Use the reference later
logger("hi")   // => hi

Now to the fun part which I haven’t used until today: you can do the same with methods when you don’t know the object, yet.

Sticking to the example from above:

class Server {
    func fetchData(completion: (data: NSData?) -> Void) { /* ... */ }
}

let fetchDataFromServer = Server.fetchData

When you have an object, the following calls will produce the same result:

let aServer = Server()
fetchDataFromServer(aServer) { data in
    // ...
}
aServer.fetchData() { data in
    // ...
}

You’ll see:

  • fetchDataFromServer is of type (Server) -> ((NSData?) -> Void) -> Void, while
  • server.fetchData is of type ((NSData?) -> Void) -> Void.

This looks just like what we tried with currying from above. Even though this might not even be the same mechanism, from a pragmatic point of view calling ClassName.methodName does the same to the method like creating a curried static variant of it.

Real-world example

I used it to produce function pointers instead of delegating directly. Say I have over-specified my methods somewhere, like so:

extension Coordinates {
  
    func moveUp() -> Coordinates {
        // y - 1
    }
  
    func moveDown() -> Coordinates {
        // y + 1
    }
  
    func moveLeft() -> Coordinates {
        // y - 1
    }
  
    func moveRight() -> Coordinates {
        // y + 1
    }
}

These explicit methods are a pain: they over-specify the changes that are possible by defining methods for each of the directions. I’d prefer to type the directions instead to make the interface cleaner:

enum Direction {
    case Up
    case Down
    case Left
    case Right
}

To leverage the existing code before refactoring, I found a switch helpful that doesn’t delegate from Direction back to Coordinates, at least not directly:

extension Direction {
    
    var offsetCoordinates: (Coordinates) -> () -> Coordinates {
        switch self {
        case Up: return Coordinates.declinedRow
        case Down: return Coordinates.advancedRow
        case Left: return Coordinates.declinedColumn
        case Right: return Coordinates.advancedRow
        }
    }
}

extension Coordinates {
  
    func offsetIn(direction: Direction) -> Coordinates {
        return direction.offsetCoordinates(self)()
    }
}

offsetCoordinates produces references to the overly explicit methods of Coordinates. Instead of requiring a reference to a coordinate object, the property doesn’t need anything at all. The resulting closure will require a coordinate to pull the method down to the instance level again:

direction.offsetCoordinates(self)

The result itself is a reference to one of the “move” methods and needs to be executed as well:

direction.offsetCoordinates(self)()
//                               ^^

Now I don’t know when you’re going to need stuff like this, but if you do, don’t be afraid to try it out.

In this particular case the intermediate solution was “clever” but inferior to defining a new move(direction: Direction) method with a new kind of Direction that can apply itself:

struct Direction {
    static let Up    = Direction( 0, -1)
    static let Down  = Direction( 0,  1)
    static let Left  = Direction(-1,  0)
    static let Right = Direction( 1,  0)
    
    let offsetX: Int
    let offsetY: Int
    
    init(_ offsetX: Int, _ offsetY: Int) {
        
        self.offsetX = offsetX
        self.offsetY = offsetY
    }
}

The Swift Developer’s Cookbook Review

photo of the ebook
Keeping the e-book handy on a tablet stand works great; copy and paste out of the PDF not quite so much

Although I knew there’s a “cookbook” book series, I haven’t read any of these before I read Erica Sadun’s The Swift Developer’s Handbook. The code listings are called “recipes”, and most of the time rightly so: I bet I copied about a dozen of the recipes into my own handy code snippet index to extend Swift’s capabilities with super useful things like safe Array indexes.

I am under the impression that I am quite an expert at Swift after about 2 years of daily practice. I know what I still don’t know. In Erica’s book, only little of this stuff was addressed. It’s not a beginner’s guide, either, though. It is aimed at programmers that want to grasp the language. There’re no exercises for the reader. This book is a handbook. You use it to get a deep understanding of the language.

The table of contents reflects this fact:

  1. Welcome to Modern Swift: migrating Swift code, REPL, scripting, command line
  2. Printing and Mirroring: how mirrors and debug output relate to printing, Quick Look support, and header doc syntax (I’m always amazed how much low-level printing features are available which I don’t need in my work)
  3. Optionals?!: unwrapping Optionals first and foremost
  4. Closures and Functions: anatomy of a function, tuples, currying
  5. Generics and Protocols: how these two overlap and require each other
  6. Errors: assertions and throwing, 7 Swift error rules, throwing errors with context
  7. Types: reference vs value types, enums, option sets, classes, property observers
  8. Miscellany: custom operators, String and sequence utilities

Although the topics become more complex in later chapters, I didn’t find the order to be very important. The chapter on errors could’ve come later or earlier in the book, for example. A recipe from the “printing” chapter used a custom operator. – Again, this is a handbook, not a learning guide.

The term “cookbook” fits nicely. Not only are code listings called “recipes”, but the kind of listing really are copy-and-paste usable for you and your work. The explanations don’t go deep; there’s no discussion about how the compiler works. But they go deep enough so you have a criterion to decide: should you use a final class for optimized access, or should you use a struct value type instead?

I got a review copy of this book for free, which I’m thankful for because of its nature to be a handbook to look up something. Its recipes surprised me since I don’t know a lot about using sequence types in clever ways, for example. I doubt I would’ve bought it, though, because the topics are so general. Still I love that I’ve learned some new details.

This makes giving a recommendation very hard.

  • If you need a guide to learn programming for Mac or iOS, this is the wrong book. Erica doesn’t touch Cocoa (AppKit or UIKit) programming. This book is fully centered around the language itself. Except maybe 3 recipes that cast String to NSString and thus require the Foundation library, everything you can learn from this book applies to Swift developers on any platform – be it coders using a Mac, Windows, or Linux machine.
  • If you want deep expert-level insights into how you can use associated types in protocols and lift them to generics so you can build custom types that rely on these – i.e. how SequenceType/AnySequence relate to one another –, this book isn’t for you, either. You won’t become a wizard of functional programming, either. Or application modeling.

It’s aimed at people looking to get past literal translation from Objective-C patterns to Swift. This book is for those who already have programming knowledge. It’s for you if you want to become a Swift developer and learn the foundational principles.

In other words: if you want to add this new language to your tool-belt, or if you want to apply for modern iOS and Mac jobs, then you should read this book and keep it in arm’s reach.

Buy The Swift Developer’s Cookbook from amazon

If you want to take the next step, Advanced Swift goes very deep.

Subscribe to the Clean Cocoa Newsletter!

Write clean code effortlessly and become a happy programmer. Let me help you get the latest recommendations on time. No spam, guaranteed.

* indicates required