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 ready to be copied into your app.

Location Matters

The location of a piece of code always matters. I was fiddling with the Charts library today and found out that if you set a chart’s data to nil, it renders some informative text by default. My data source doesn’t pass nil but an empty array around, though, so I had to convert empty arrays to nil to make use of this feature.

Take this simple code:

func drawLineGraph(dataPoints: [DateBasedDataPoint]) {

    guard !dataPoints.isEmpty else {
        chartView.data = nil
        return
    }

    chartView.data = lineChartData(dataPoints: dataPoints)
}

private func lineChartData(dataPoints dataPoints: [DateBasedDataPoint]) 
    -> LineChartData {
    /* ... */
}

That’s my API’s entry point. The logic is simple enough and it achieves the desired effect. Either set data to nil or transform the values.

Now take this other version after a simple refactoring:

func drawLineGraph(dataPoints: [DateBasedDataPoint]) {

    chartView.data = lineChartData(dataPoints: dataPoints)
}

private func lineChartData(dataPoints dataPoints: [DateBasedDataPoint]) 
    -> LineChartData? {
        
    guard !dataPoints.isEmpty else { return nil }
    
    /* ... */
}

There, the conversion function takes care of returning nil if the dataPoints array is empty.

What’s the gain?

The drawLineGraph method now only takes care of obtaining compatible values and assigning them to the chartView. It doesn’t know what else to do with the dataPoints. Before, the method had knowledge of doing 2 things: obtaining values or setting the chartView to an “empty” state, depending on knowledge about the dataPoints.

Even though the guard statement is quite similar, moving the decision to a place where intimate knowledge about creating chart view data is required makes more sense and simplifies the call site (drawLineGraph).

When I’m done fiddling around with this, I can promote the conversion from a private method into an object on its own. Then the converter will have all the knowledge required to create data that the Charts library understands.

objc.io Books 30% Off

books screenshot

All 3 amazingly useful objc.io books are 30% off this week. Grab all three of them in a bundle and save even more.

If you use my link, I’ll even get a small kickback thanks to their affiliate program. I wholeheartedly recommend you take at least the time to read the samples. The team updates their ebooks regularly, and you’ll get a Swift 3.0 edition later this year, too.

Disabling Segments in a NSSegmentedControl in a Toolbar

Earlier this week I posted how to create a segmented toolbar item with 1 label for each segment. Now some options in TableFlip depend on context: without a selected cell, you cannot remove the selection, for example. So I disabled some segments and it looked alright:

disabled segments screenshot
How the segments should look with 2/3 disabled

Easy enough:

let enabled = hasSelection()

ThisParticularSegmentedControl.contextualSegments // = (0...1)
    .forEach { (segment: Int) in
        self.setEnabled(enabled, forSegment: segment)
}

But even though it’s disabled, and even though the NSSegmentedControl’s trackingMode is set to NSSegmentSwitchTracking.Momentary, clicking a disabled segment in the toolbar results in a permanent disabled-looking selection:

selected disabled segments screenshot
Disabled but toggled segment

I tried a ton of different things, including, but not limited to:

  • when the selection changes, deselect the segment again
  • when the toolbar validates, set selectedSegment = -1 (“no selection”)

The problem isn’t with the NSSegmentedControl, though. It’s with the NSToolbarItem that corresponds to the disabled segments!

So during NSToolbarItemGroup.validate() in my custom subclass I disable the corresponding subitems, too.

Some Example Code

This is the group:

class ToolbarItemGroup: NSToolbarItemGroup {

    convenience init(itemIdentifier: String, validator: ActionItemValidation) {

        self.init(itemIdentifier: itemIdentifier)

        self.validator = validator
    }

    var validator: ActionItemValidation!

    override func validate() {

        validateSubitems()
        validateSegmentedControl()
    }

    private func validateSubitems() {

        self.subitems.forEach(validator.validate)
    }

    private func validateSegmentedControl() {

        guard let segmentedControl = self.view as? AddDimensionSegmentedControl 
            else { return }

        validator.validate(segmentedControl: segmentedControl)
    }
}

The ActionItemValidation type exposes two relevant methods:

  1. validate(segmentedControl:)
  2. validate(toolbarItem:)

The validate(toolbarItem:) variant existed already to enable/disable buttons in the toolbar. I achieve this by tagging the items, for example:

  • 0 equals “always on”,
  • 1 equals “enable only for selections”.

Re-using the method here was easy. I only had to set the tag for the group’s affected subitems.

How to Create a Segmented NSToolbarItem like Apple Mail.app

Ever wondered how Apple Mail’s NSToolbar achieves the effect of individually labeled buttons shown in groups?

mail toolbar screenshot
Screenshot of Mail on OS X 10.11

If you know your AppKit, you’ll try to drag a NSSegmentedControl into the toolbar and fiddle around with it. But there’ll only be one label for the entire NSSegmentedControl.

The solution is simple but weird: there’s a NSToolbarItem subclass called NSToolbarItemGroup which can group a collection of NSToolbarItems so they can be moved around together only. In combination with a NSSegmentedControl you can label each segment individually.

You have to get out of Interface Builder for this and customize your NSToolbarDelegate to return a NSToolbarItemGroup instance:

let group = NSToolbarItemGroup(itemIdentifier: "NavigationToolbarItems")

// First add subitems
let itemA = NSToolbarItem(itemIdentifier: "PrevToolbarItem")
itemA.label = "Prev"

let itemB = NSToolbarItem(itemIdentifier: "NextToolbarItem")
itemB.label = "Next"

group.subitems = [itemA, itemB]

// ... then add a custom `view`
let segmented = NSSegmentedControl()
group.view = segmented

The weird thing about this is that you add both one subitem for each segment and the NSSegmentedControl as the group’s own view.

The segment labels will be obtained from the NSToolbarItems. Don’t set a label for the segments themselves (via NSSegmentedControl.setLabel(_:, forSegment:)) – these will be drawn inside the controls.

Fully Working Sample App

sample app screenshot
The resulting sample toolbar
  1. Create a new OS X/Cocoa project
  2. Paste the following code into AppDelegate.swift
  3. There is no step 3
import Cocoa

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate, NSToolbarDelegate {

    @IBOutlet weak var window: NSWindow!

    var toolbar: NSToolbar!

    let toolbarItems: [[String: String]] = [
        ["title" : "irrelevant :)", "icon": "NSPreferencesGeneral", "identifier": "NavigationGroupToolbarItem"],
        ["title" : "Share", "icon": NSImageNameShareTemplate, "identifier": "ShareToolbarItem"],
        ["title" : "Add", "icon": NSImageNameAddTemplate, "identifier": "AddToolbarItem"]
    ]

    var toolbarTabsIdentifiers: [String] {

        return toolbarItems.flatMap { $0["identifier"] }
    }

    func applicationDidFinishLaunching(aNotification: NSNotification) {

        toolbar = NSToolbar(identifier: "TheToolbarIdentifier")
        toolbar.allowsUserCustomization = true
        toolbar.delegate = self
        self.window?.toolbar = toolbar
    }

    func toolbar(toolbar: NSToolbar, itemForItemIdentifier itemIdentifier: String, willBeInsertedIntoToolbar flag: Bool) -> NSToolbarItem? {

        guard let infoDictionary: [String : String] = toolbarItems.filter({ $0["identifier"] == itemIdentifier }).first
            else { return nil }

        let toolbarItem: NSToolbarItem

        if itemIdentifier == "NavigationGroupToolbarItem" {

            let group = NSToolbarItemGroup(itemIdentifier: itemIdentifier)

            let itemA = NSToolbarItem(itemIdentifier: "PrevToolbarItem")
            itemA.label = "Prev"
            let itemB = NSToolbarItem(itemIdentifier: "NextToolbarItem")
            itemB.label = "Next"

            let segmented = NSSegmentedControl(frame: NSRect(x: 0, y: 0, width: 85, height: 40))
            segmented.segmentStyle = .TexturedRounded
            segmented.trackingMode = .Momentary
            segmented.segmentCount = 2
            // Don't set a label: these would appear inside the button
            segmented.setImage(NSImage(named: NSImageNameGoLeftTemplate)!, forSegment: 0)
            segmented.setWidth(40, forSegment: 0)
            segmented.setImage(NSImage(named: NSImageNameGoRightTemplate)!, forSegment: 1)
            segmented.setWidth(40, forSegment: 1)

            // `group.label` would overwrite segment labels
            group.paletteLabel = "Navigation"
            group.subitems = [itemA, itemB]
            group.view = segmented

            toolbarItem = group
        } else {
            toolbarItem = NSToolbarItem(itemIdentifier: itemIdentifier)
            toolbarItem.label = infoDictionary["title"]!

            let iconImage = NSImage(named: infoDictionary["icon"]!)
            let button = NSButton(frame: NSRect(x: 0, y: 0, width: 40, height: 40))
            button.title = ""
            button.image = iconImage
            button.bezelStyle = .TexturedRoundedBezelStyle
            toolbarItem.view = button
        }

        return toolbarItem
    }

    func toolbarDefaultItemIdentifiers(toolbar: NSToolbar) -> [String] {

        return self.toolbarTabsIdentifiers;
    }

    func toolbarAllowedItemIdentifiers(toolbar: NSToolbar) -> [String] {

        return self.toolbarDefaultItemIdentifiers(toolbar)
    }

    func toolbarSelectableItemIdentifiers(toolbar: NSToolbar) -> [String] {

        return self.toolbarDefaultItemIdentifiers(toolbar)
    }

    func toolbarWillAddItem(notification: NSNotification) {

        print("toolbarWillAddItem", (notification.userInfo?["item"] as? NSToolbarItem)?.itemIdentifier ?? "")
    }

    func toolbarDidRemoveItem(notification: NSNotification) {

        print("toolbarDidRemoveItem", (notification.userInfo?["item"] as? NSToolbarItem)?.itemIdentifier ?? "")

    }

    func applicationWillTerminate(aNotification: NSNotification) {
        // Insert code here to tear down your application
    }

}

Update 2016-06-16: Enabling/disabling segments in the toolbar takes a bit of extra work. In short, you have to both disable the segment through the NSSegmentedControl and the corresponding NSToolbarItem. I wrote a follow-up post about disabling segments.

Coding TableFlip: the Bigger Picture

Now that TableFlip is nearing completion, I want to share details of how I created this piece of software with you.

Today, I’ll start with the bigger picture: the application architecture.

Starting with ReSwift

Earlier this year, I got to know ReSwift from a talk by Benjamin Encz which I loved.

I got in touch with the team and contributed a bit to the codebase myself. To get a feeling for it, I created a still unfinished sample To Do list app. (I’m going to finish the app for the course of a small book on ReSwift this year, don’t worry guys!) When I started to work on TableFlip I leveraged my knowledge of ReSwift to give the approach a real world pressure test.

So I started the app with ReSwift in mind. ReSwift doesn’t impose external constraints to the development process that really matter. ReSwift takes care of keeping the app state consistent and to model the flow of information properly. That’s a huge win.

Ditching ReSwift later won’t hurt your code much, though: ReSwift doesn’t dictate an approach to software architecture. It simply takes care of passing data around and maintaining a consistent overall app state.

ReSwift became the kind of glue that holds moving pieces of TableFlip together. To make sense of this weird metaphor, let’s have a look at the overall app architecture first.

Application Architecture

The app’s architecture is not affected a lot by ReSwift. ReSwift takes care of event dispatch, but only in a very small portion of the code base. In terms of process, it’s a central piece of logic. In terms of creating the parts or structure of the app, ReSwift’s portion is negligible.

The App’s Heart: the Model

model files in Xcode
Model group of the project in Xcode

When I started to develop TableFlip, I started what I believe to be the most important part: the model.

It’s most important because it encapsulates all core rules to the “table flipping” domain. It is a model of the problem domain: editing tabular data with multiple sheets in a single document. Tables can be resized; tables can be removed from the document; table cells can be edited and moved. These are only a few of the foundational pieces from the problem domain. When these are modeled well, creating a Cocoa Mac app on top of it is a piece of cake.

TableFlip’s model is very expressive on the inside while exposing a simple interface to the rest of the app. I won’t go into detail for every piece of code I wrote. Here are the most important protocols and some primitive value types for a brief overview:

  • TableRepresentation is a protocol that defines how you can query something for Cells at specific Coordinates, for example. It exposes the overall TableSize.
  • MutableTableRepresentation is an extension to TableRepresentation and provides means to overwrite cell data, insert Rows and Columns, and resize the table.
  • SelectableTable is a protocol that exposes info about which Cells in a table are selected; moving or expanding the selection into a Direction is possible, too.
  • Table implements the table representational protocols and SelectableTable. It’s the foundational

The value types I used are probably the most powerful part:

Coordinates are provided as pairs of Indexes. An Index is an unsigned integer under the hood, restricted to values of 1 (not 0!) and above. With these I don’t have to worry about illegal coordinates like (-1, -1) because the types I use don’t allow those.

In other words, instead of defensive programming I encapsulate rules in types. With guarding against illegal values throughout the app a similar effect could have been achieved. It would have come at a high cost, though, spreading business rules all over the place. Instead of replicating the guard statement wherever necessary, I use types that incorporate all the knowledge and make my app a lot more robust.

Index is also a ForwardIndexType so I can create collections based on them. Another place where I don’t have to worry about special conditions – I simply employ the Index type as the collections index and can have piece of mind.

So a Table object is really at the core of everything. You ask it for data with Coordinates and query for rows and columns by Index; overwriting cell data happens through passing a NewCell object in. The Table takes care of everything else. It manages its boundaries (literally, too: it doesn’t insert data beyond the TableSize) and “client code” can rely on it working correctly. On top, there’s tons of unit tests to verify I don’t break anything.

Editing CSV files solely depends upon manipulating a single Table instance and persisting its state. Easy.

The Markdown-related types are a bit more intricate. A Markdown file can have multiple tables in it with regular text in between. So I have added MarkdownContents to represent a Markdown file. It is made of MarkdownParts, either .text or .table, to represent a sequence of content sections. When you save the Markdown file in TableFlip, you expect the text contents to stay intact, so I have to keep these save.

Also, a MarkdownTable can come in many variants: no surrounding pipes at all, leading pipes, trailing pipes, and pipes both at the beginning and end of the line. Thus a MarkdownTable is not much more than an adapter for a regular Table with a few extensions.

If I were to write a command line application, the model would be able to represent the file contents. All I’d need is some way to import and export file data. The model is the mutable representation of the tables itself. It adds a meaningful layer of abstraction to “adding text and pipes to a string in a file”. Instead of operating on the text level and counting characters, a Table helps the developer to express her thoughts in means of insertRow(above:) and changeCell(at:, contents:).

Import and Export

The model already sports behavior. You can add, move, select, delete and insert stuff. That’s a language which makes changing tabular data easy. Coming up with and realizing such a language arguably is the only job we programmers really have. The rest is adding user interface chrome and algorithms to realize use cases.

TableFlip to me is very much centered around file operations: opening Markdown files, changing stuff, then saving back the changes. So the first layer around the model is file I/O: importing and exporting CSV and Markdown files.

Parsing CSV is piece of cake. There’s some kind of delimiter (tab character, comma, semicolon, whatever) and each row has its own line. Read and parse the file, create a Table from it, and you’re done.

Parsing Markdown files is a bit more cumbersome: you have to skip non-table content until a line appears that could be part of a table. When the table ends, you have to collect all the Markdown that follows until the next table begins (or the file ends). As I said above, tables come in different variants, too:

No | Pipes
at | all

| Leading | Pipe
| on each | line

Trailing | Pipe |
on each  | line |

| Surrounding | Pipes      |
| just        | everywhere |

Once finding out when a table starts, how long it continues, and deciding of which variant it is, you’re set. It’s still not a lot of work but error-prone. Again, unit tests and file-based fixtures to the rescue.

The User Interface on the Outside

Until I write really complicated applications, I simply architect them in layers. The model is at the core with all its business logic. Naturally, the user interface is at the outside. In terms of user interaction, this is as far away from the core as it gets. One step further and you’d bypass everything AppKit or Cocoa offers, dealing with hardware signals directly. No, thank you – this is how the operating system enables the user to manipulate the application, so it sits at the boundary of the outside world for me.

I use Interface Builder and AutoLayout for creating the visual representation of a document window. There’s buttons, menus, and a table. Utilizing the responder chain is helpful to centralize handling of interactions. I won’t go into much detail on handling UI events here.

When the Cocoa NSView components the user sees on the screen are the outer edge, then dispatching events the app understands is the inner edge. In between is all the view setup and view controller stuff.

The kind of events the user interface layer emits are ReSwift-compatible Action types.

depiction of the layers
ReSwift powers the mediation from UI interactions to model changes and helps updating the view with the current state.

So ReSwift is the ultimate translation of UI interactions to events that change the app’s state. This in turn is using the model. The altered model then is pushed to observers. One of these is the Presenter which tells the view to update itself with a view model that is derived from the new state.

The Ominous Application Layer: Glueing State to the View

In TableFlip, there’s not much need for a traditional “Application Layer” that takes care of responding to events. If I weren’t using ReSwift, I’d write event handlers in this layer between UI and model. This is what makes the particular app what it is, for example:

  • either a shell program (writing text to stdout),
  • a Cocoa application (orchestrating display of AppKit windows),
  • or a server (assembling JSON and sending it off to clients).

Since both the UI and model are self-contained, merely NSDocument subclasses and a TablePresenter live in this layer.

Because there’s a portion dedicated to ReSwift state updates elsewhere, the presenter takes care of view updates through protocol it owns. It’s so simple I show its public interface to you in full:

protocol DisplaysTableDocument {
    func showTableDocument(viewModel: DocumentViewModel)
}

protocol DisplaysTable {
    func showTable(viewModel: TableViewModel)
}

class TablePresenter {

    typealias View = protocol<DisplaysTable, DisplaysTableDocument>

    let view: View

    init(view: View) {
        self.view = view
    }
}

extension TablePresenter: StoreSubscriber {

    // ReSwift state observation entry point:
    func newState(state: DocumentState) {

        let documentViewModel = self.documentViewModel(documentState: state)
        let tableViewModel = self.tableViewModel(documentState: state)

        view.showTableDocument(documentViewModel)
        view.showTable(tableViewModel)
    }

    private func documentViewModel(documentState state: DocumentState) -> DocumentViewModel {
        /* 10 simple lines of logic */
    }

    private func tableViewModel(documentState state: DocumentState) -> TableViewModel {
        /* Another 8 lines of logic */
    }
}

Notably, the Application Layer defines the protocols a compatible view has to implement. Not the other way around. The presenter does not depend upon the view; the view has to meet requirements of the application instead. This helps to hide details of the UI and prevents me from reaching deep into window controllers and the like. They have to take care of everything themselves once they receive a view model.

In other words I am inverting the dependencies for cleaner boundaries between layers and in turn achieve relative independence of the application from the view layer.

This approach would make it possible to write multiple views and create different app targets, each with its own view implementation. The standard example is a terminal application VS a graphical user interface app. That doesn’t make much sense in my case. But if cross-platform Swift truly takes off, I can write a Linux and a Windows front end to the app simply by plugging-in a new view incarnation.

Conclusion

I employed a layered architecture approach – because I knew that I wanted to separate the model from the view cleanly, and because overall app state transitions with ReSwift are independent from the rest of the code anyway. These two isolated layers, model and view, made putting the rest into place very easy.

I don’t think twice if I should write clean code. That’s about the only ideal I always try to meet. From there it follows that sub-components, modules, or layers of my app on a macro-scale should themselves be “clean.” Whatever that means in the end – the intention is the same with every project I take on.

Among the benefits of clean layer boundaries, simplicity of interaction between layers is very important. If the view is tightly interwoven with the model, there hardly is a clean boundary. If the view exposes how it will encode user interactions as events and if the model exposes a public interface to perform changes, you only need very simple glue code to translate one to the other. The “glue” has to know both interfaces. View and model don’t have to know each other at all, though.

If something in the view is broken, I know where to look and which part of the code I can ignore. If the model doesn’t do what I intended, it doesn’t matter if the event originates in a button click or a direct method invocation from a unit test; I know where to look for faulty code.

Separation facilitates isolation; isolation facilitates clean thinking and in turn increases maintainability. You don’t have to think about the app as a whole but can focus on its sub-systems instead.

The benefit of cleanly separated layers is that their boundaries increase cohesion inside the layers and help not create a mess of everything. A model object should never need to know anything about how a NSView works, so when you perform changes on model code, you can forget about AppKit (or UIKit, respectively) for a while. It’s only the tiny world you created that matters.

Most of this is targeted at keeping code readable. Writing an app is not a “write once” think. You constantly have to revisit old code. If it is highly cohesive, you can tweak it more easily.

On top of all that, the separation enables me to rewrite parts of the application with ease. Like I said, a Linux UI or maybe an iOS app would simply require coding a new view layer, that’s all.

Layered architecture is a very simple approach to application architecture. There’re others, more complex approaches. I found layered architecture to meet my needs to isolate and solve most of my day-to-day problems, though.

I spend a lot of time with the initial model design. Once I was ready to dive into file I/O and then try to implement a NSDocument subclass, the model was further refined to meet real-world problems I didn’t think of initially. I wouldn’t ever call the model finished. That doesn’t make sense. The app as a whole is constantly improved.

Configuration Objects and the Then Microframework

When parameter lists grow or two kinds of parameters seem to go together a lot, it’s time use the extract parameter object refactoring for greater good – then you can even specify sensible defaults.

This is a typical way to pass a set of options to an objects during initialization in a language like Swift. In languages like JavaScript or Ruby, dictionaries of key–value pairs can work just as well. Using dictionaries in Swift for this can be a pain, though.

Now Soroush wrote about a way that uses the Then microframework as a replacement for configuaration dictionaries. This way you don’t have to promote every property to the initializer’s list of parameters. Here’s a before and after, where you can see that without then you have to write a lot of repeating boilerplate:

// Before

struct FieldData {
    let title: String
    let placeholder: String
    let keyboardType: UIKeyboardType
    let secureEntry: Bool
    let autocorrectType: UITextAutocorrectionType
    let autocapitalizationType: UITextAutocapitalizationType

    init(title: String,
        placeholder: String = "",
        keyboardType: UIKeyboardType = .Default,
        secureEntry: Bool = false,
        autocorrectType: UITextAutocorrectionType = .None,
        autocapitalizationType: UITextAutocapitalizationType = .None)
        {
            self.title = title
            self.placeholder = placeholder
            self.keyboardType = keyboardType
            self.secureEntry = secureEntry
            self.autocorrectType = autocorrectType
            self.autocapitalizationType = autocapitalizationType
    }
}

let fieldData = FieldData(title: "Password", secureEntry: true)

Now with then, making non-mandatory properties mutable and getting rid of the boilerplate:

// After

struct FieldData {
    let title: String
    var placeholder = ""
    var keyboardType = UIKeyboardType.Default
    var secureEntry = false
    var autocorrectType = UITextAutocorrectionType.No
    var autocapitalizationType = UITextAutocapitalizationType.None

    init(title: String) {
        self.title = title
    }
}

let fieldData = FieldData(title: "Password").then({
    $0.secureEntry = true
})

That’s a Swift alternative to Ruby’s hash-based option initializers. There, the dictionary’s key is used as the setter’s name which is then invoked like so:

class Example
  attr_reader :name, :age
  
  def initialize(args)
    args.each do |k,v|
      instance_variable_set("@#{k}", v) unless v.nil?
    end
  end
end

e1 = Example.new :name => 'foo', :age => 33
#=> #<Example:0x3f9a1c @name="foo", @age=33>

Principles of Object-Oriented Design in Swift 2.2

Understanding Uncle Bob’s Principles of Object-Oriented Design (which resulted in the SOLID principles) is super important to really grasp the use of design patterns (like MVVM) and architectural patterns (like VIPER). It’s like the grammar for crafting proper object-oriented software.

And now here’s the good news: there is a Swift playground (and Markdown file to read online) that illustrates all the principles by Uncle Bob: The Principles of OOD in Swift 2.2

Check it out, take notes, and keep the principles close to your heart. They may save your life someday.

TIL You Can Cancel Enqueued GCD Blocks

Today I learned that you can cancel a delayed dispatch_block_t with the new dispatch_block_cancel (available since OS X 10.10/iOS 8.0). Thanks Matt for the post – here’s a Swift example:

let work = dispatch_block_create(0) { print("Hello!") }

# Execute after 10s
let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(10 * Double(NSEC_PER_SEC)))
dispatch_after(delayTime, dispatch_get_main_queue(), work)

dispatch_block_cancel(work)
# Will never print "Hello!"

Note: canceling doesn’t work if the block is being executed.

If I knew that this API existed, I might not have used the very cumbersome approach from below in Move!.

Super-Weird Legacy Version of a Cancelable Delayed Block

For historic purposes, here’s an adaptation of the cancelable dispatch block you may find on the internet that I once have adapted for Swift:

typealias CancelableDispatchBlock = (cancel: Bool) -> Void

func dispatch(cancelableBlock block: dispatch_block_t, atDate date: NSDate) -> CancelableDispatchBlock? {

    // Use two pointers for the same block handle to make
    // the block reference itself.
    var cancelableBlock: CancelableDispatchBlock? = nil

    let delayBlock: CancelableDispatchBlock = { cancel in
    
        if !cancel {
            dispatch_async(dispatch_get_main_queue(), block)
        }
    
        cancelableBlock = nil
    }

    cancelableBlock = delayBlock

    let interval = Int64(date.timeIntervalSinceNow)
    let delay = interval * Int64(NSEC_PER_SEC)

    dispatch_after(dispatch_walltime(nil, delay), dispatch_get_main_queue()) {
    
        guard let cancelableBlock = cancelableBlock else { return }

        cancelableBlock(cancel: false)
    }

    return cancelableBlock
}

func cancelBlock(block: CancelableDispatchBlock?) {

    guard let block = block else { return }
    
    block(cancel: true)
}

The trick is this: the delayed block delayBlock: CancelableDispatchBlock captures its context where a reference to cancelableBlock is included – but not set yet. Then you make the reference point to the delayBlock itself.

The actual canceling is a fake, though. The block is still called. It aborts early if the cancel parameter is true, though.

Hustling

I was confused about the term “to hustle” for quite a while, probably because I’m non-native. I found it in various books about startups and solopreneurship, and from the context I deduced it might have something to do with marketing. Shawn Blanc was the first to make sense of this: it usually means to do a lot of work. To break a sweat working towards your goals.

Now there’s nothing wrong with this. “If you want to succeed as hard as you want to breathe, then you will succeed.” That should by no means entail you stop sleeping at all and wear your body down. After all, you and your body are one.

That’s why I’d like to add a few items to Shawn’s list:

  • Start eating real food and stop swallowing garbage.
  • Give yourself the chance to detox; remove everything that may affect your brain for a while – porn, social media, coffee, tea, sugar.
  • Exercise and move every day. Walk for 30 mins if you can’t muster the strength for anything else.

A lot of people I met in tech are interested in body-hacking, life-hacking, and the like. Optimizing sleep for example. Or ditching processed food because, you know, better focus and stuff. This is the search for technical solutions (stuff you set up once and then do it like an automaton) when the underlying challenges are those a corporeal life itself presents.

The fundamentals are the same no matter if you want to be a healthy over-performer in tech or a professional athlete: push your limits and swing the pendulum back and forth from stress to relaxation: Fast and eat; exercise and rest; work and meditate. Your performance is not only about how quick you can throw together a working app. It’s also about how long you can excel at what you do before wearing out.

So take care, don’t overwork, don’t underwork, and push yourself on all frontiers in life at once.

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