Hipster Swift: Demystifying the Mysterious


日本語訳はここで見つけることができます

The thing I love most about Swift is that it's so very easy to use. It reads like a book, and I love reading books. 🤓 At a high level, Swift is amazing and brings so much to us developers to use on a daily basis. However, there are many little-known things in Swift that can save us time and energy if we memorize a few key features. They may not read like a book sometimes, but hopefully this post can help you decrypt what some of these features mean!

Now this post is a bit lengthy, but what's awesome about it is that you don't need to read everything one after another to get some use out of it. Each section is it's own thing so feel free to skip from one section to another. For your convenience, here is a link to each part of this post:

@noescape

This little ditty seems to be gaining steam in Swift. Before I knew what it was, every time I saw it my eyes immediately glazed over. I tell myself it's the tool of the Rob Gods, @rob_rix and @cocoaphony. But what does it actually mean though?

Turns out, it's pretty damn useful. It's a Swift attribute that's applied to the parameter of a function like so:

func prepareTheKrakenArmyForBattle(@noescape preparations: () -> Void) {
    //Make the preparations to consume the human race.
}

What it basically does is tell the compiler that the passed-in closure can NOT be used outside the body of the function it's passed into. Because closures are first-class citizens in Swift, you have the capability to store closures inside of variables to be used anywhere/anytime that you want. By marking a closure within a function as @noescape, you are telling the compiler that the closure you pass in will be executed or torn down within the body of that function and nowhere else.

An easy way of thinking about it is that the body of that function serves as a jail, and that closure is trapped inside the body of the function with no means of escape.

Here's a great image of a closure trying to escape (as you can see, the Swift compiler is having none of it.):

One awesome plus is that it by using the @noescape attribute, the compiler will further optimize your non-escaping code actually give you compiler optimizations for your code as well.

Another awesome plus is that within the body of a non escaping closure, you don't need to explicitly capture self, weakly or otherwise. Since the non-escaping closure will be executed or torn down by the end of the function that it's a parameter of, there is no need to mess with capture semantics for that closure. This allows for awesome code that looks like this:

class Kraken {}
class KrakenGeneral {
    var soldiers = [Kraken]()

    func startTheWar() {
        prepareTheKrakenArmyForBattle(punishments: {
            soldiers.removeFirst() //notice that we don't need self here.
        })
    }

    func prepareTheKrakenArmyForBattle(@noescape punishments punishments: () -> Void) {
        if someoneReportedMisbehavior {
            //Someone was misbehaving. Helping out the humans. We can't have that now.
            punishments()
        }
    }
}

Back to Top

@autoclosure

@autoclosure is another Swift attribute that you may have seen but can't figure out what it does. It's pretty similar to the @noescape attribute. First, it can only be applied to closure parameters, and the use of @autoclosure automatically applies @noescape for that closure parameter.

The @autoclosure attribute delays the execution of a function that's activated in a function parameter. Essentially, calling a function inside of a parameter will wrap the function call in a closure for later use in the function body. For example, you may see a lot of code that does this:

krakenGeneral.punishSoldier(soldiers.removeFirst())

func punishSoldier(soldier: Kraken) {
    throwSoldierInTheBrig(soldier)
    sendSoldierHomeToMommy(soldier)
}

Here, as soon as the krakenGeneral calls the punishSoldier() function, the removeFirst() function gets called. This immediately removes the first object in the soldiers array and returns that object to be passed in to the soldier parameter. Then, you do what you will with the offending kraken soldier. But what if you don't want the first soldier to be removed until later? What if you're a compassionate Kraken Officer? What if you want to give the poor guy a chance before sending him home to his mommy?

Enter @autoclosure.

Because @autoclosure wraps the passed in parameter in a closure, we can put off the removal of the soldier until we deem best in the body of the punishSoldier() function like so:

//The removeFirst() function won't get called here.
punishSoldier(soldiers.removeFirst())

//@autoclosure can only be used on closure types. Let's match our parameter to the removeFirst() function type.
func punishSoldier(@autoclosure soldierPunishment: () -> Kraken) {
    //Now we can decide when to remove our soldier.
    if someoneReportedMisbehavior {
        //This will remove the soldier and send that soldier home.
        sendSoldierHomeToMommy(soldierPunishment())
    } else {
        apologizeToSoldierAndFeedHimAHuman()
    }
}

At a high level, the above code is equivalent to this:

punishSoldier {
    soldiers.removeFirst()
}

func punishSoldier(@noescape soldierPunishment: () -> Kraken) {
    if someoneReportedMisbehavior {
        //This will remove the soldier and send that soldier home.
        sendSoldierHomeToMommy(soldierPunishment())
    } else {
        apologizeToSoldierAndFeedHimAHuman()
    }
}

The main difference in syntax is at the call site. The @autoclosure attribute isn't used often because the use of it can make your code a bit unreadable. In our first example, if we didn't know the contents of our punishSoldier() function, we still assume that the first object of our soldiers array has been removed. Because of @autoclosure, it hides the implementation of our closure parameter. Hiding implementations are almost never a good thing. Personally, I would suggest against using it unless it makes sense what is happening.

Previously, I mentioned that using @autoclosure automatically turns the closure parameter into a non-escaping closure. If you really want the closure to escape for whatever reason, you can apply an additional attribute to @autoclosure like so:

var storageForAClosure: (() -> Bool)?

func executeFunctionWithEscapableClosure(@autoclosure(escaping) houdiniClosure: () -> Bool) {
    storageForAClosure = houdiniClosure
}

executeFunctionWithEscapableClosure("kraken".hasPrefix("k"))
storageForAClosure?() //hasPrefix doesn't execute until this line of code

By putting the keyword escaping inside of parentheses to the right of the @autoclosure attribute, you are telling the compiler that the closure parameter is an escaping closure.

Back to Top

Inline Lazy Vars

This may not be new to you guys but either way, I feel this deserves a spot on the Hipster Swift board. I'm sure we all know what a lazy variable is. In case you don't, it's essentially an instance variable that is initialized only once throughout the lifetime of an object, and returns it's one-time-initialization value everytime you access it. This is useful for computationally-intensive values or when a property's value isn't known until after the the object it belongs to is created. For the most part, we create lazy variables like this:

class KrakenFoodGenerator {
    lazy var lazyHuman: Human = {
        //We want a lazy human. Kraken's get annoyed 
        //when they have to chase their food.
        return self.generateWithOptions(.Lazy)
    }()
}

Swift makes lazy initialization very easy but I get kind of annoyed when I have to put a lazy variable in my variable list and it takes up so much space. Awesomely enough, the good Humans over on the Swift team thought of this for us. We can inline our lazy vars and reduce the above code to one line:

class KrakenFoodGenerator {
    lazy var lazyHuman: Human = self.generateWithOptions(.Lazy)
}

But wait, that's weird...we're using self in the variable declaration! What kind of self is it? Will it give us a retain cycle? Lazy vars are just closures after all. How come I can use self here but not when the lazy keyword is applied?!

Well, I can't really tell you how that's possible. However, after writing the autoclosure section above, I can make a very good guess. It seems as though anything after the equals sign of a lazy variable is automatically wrapped in a closure for us. As for the use of self, it does capture it strongly. However, you shouldn't run into a retain cycle and here's the proof:

Cool, huh? Now you can go and shorten some code. Lord knows that's exactly what I'm about to do.

EDIT:
After giving a talk at the try! Swift Conference in Japan, I was pointed to a pretty enlightening tweet by @aligatr from the wonderful @jckarter:

This totally means that our inline lazy vars are wrapped in a noescape closure so we have proof that we can't get a reference cycle while using them! (Unless of course, you happen to have a lazy closure variable. You should still be careful of those.):

Back to Top

()() - AKA Currying

Yet another weird one. First time I saw this, it threw me for a loop. Coming from Objective-C, it was a little difficult to wrap my head around multiple parentheses. For the most part, Currying deserves it's own blog post. I personally don't use it but objc.io wrote a great section on it and this guy wrote a great post on it too.

At a high level, it's very much a great way of representing chained functions that curry/apply a parameter from one function to the next. If you never saw double parentheses before, you would most likely write chained functions like this:

func fourChainedFunctions(a: Int) -> (Int -> (Int -> (Int -> Int))) {
    return { b in
        return { c in
            return { d in
                return a + b + c + d
            }
        }
    }
}

fourChainedFunctions(1)(2)(3)(4)

See, now that's a pretty terrible way to live. It's nice if you wanted to have mix and match functions and such, but for the most part, there are no named parameters in the nested return functions and that return pyramid of doom makes me want to run for the hills. Currying your functions at the function declaration makes this a lot more readable. The above code, using currying, is equivalent to this:

func fourChainedFunctions(a: Int)(b: Int)(c: Int)(d: Int) -> Int {
    return a + b + c + d
}

In my opinion, that's a LOT more easily digested. Pretty code is healthy code, folks.

NOTE TO ALL THE HIPSTAS OUT THERE: Currying syntax will be removed. Personally, this isn't too big of a problem for me since I never had the need to use currying, but for all of you functional programmers out there who liked it: I'll pour a little beer out for you. I must say, I am gonna miss the ability to make code a little prettier if I needed it. For now, I will have to welcome our nested-closure-pyramid-of-death overlords.

Back to Top

That Weird Ellipse Thing (Variadic Parameters)

I tell you what, Swift is chockfull of weird function things. Variadic parameters are yet another example of this. You may have seen this floating around in your code somewhere:

func printEverythingWithAnEmojiInBetween(objectsToPrint: Any...)

Those three dots there (the ellipses) are what make the parameter variadic. Simply put, the parameter is a sequence and can be enumerated like one. To fill out our function (and to show you how to actually use a variadic parameter), check this code out:

func printEverythingWithAKrakenEmojiInBetween(objectsToPrint: Any...) {
    for object in objectsToPrint {
        print("\(object)🐙")
    }
}

//This will print "Hey🐙Look🐙At🐙Me🐙!🐙"
printEverythingWithAKrakenEmojiInBetween("Hey", "Look", "At", "Me", "!")

Yep. That's right. A for-in loop. And a comma-separated list. That's how you use it. As a matter of fact, variadic parameters are how Swift's print function works.

Back to Top

dynamic

The dynamic keyword is a declaration modifier that you can apply to either function or variable declarations. You may see this when using libraries like NewRelic or something similar for app analytics. What dynamic does is tells the runtime to use dynamic dispatch over static dispatch for the function or variables modified. It also implicitly adds the @objc attribute to the variable or function declaration.

As an important note, anything using the dynamic keyword uses the Objective-C runtime instead of the Swift runtime to dispatch messages to it.

Now we love static dispatch. However, app analytics doesn't like it so much. It's hard to generate and insert analytics code dynamically when functions are mostly static by default. Dynamic is useful for these situations but sacrifices optimizations we get from static dispatch. The use of dynamic looks like this:

class Kraken {
    dynamic var imADynamicallyDispatchedString: String

    dynamic func imADynamicallyDispatchedFunction() {
        //Hooray for dynamic dispatch!
    }
}

The other thing you get by using dynamic dispatch is better interoperability with things that use magic in the Objective-C runtime like Core Data that rely on KVC/KVO (think data bindings) at runtime. By using dynamic, you can take advantage of things we have long taken for granted in the Objective-C runtime. You know, just in case Swift wasn't cool enough for your needs. 😎

Basically, if you know that a certain function or property will be interfered/replaced/swizzled by someone at runtime, then it's a good idea to mark it dynamic. If you don't, you could get a crash from the compiler devirtualizing access/inlining implementations (this is an optimization you get for free) to your functions even though other code is trying to use runtime magic that doesn't play well with those optimizations.

Back to Top

Special Literals: FILE, LINE, COLUMN, & FUNCTION

AKA Messrs #file, #line, #column, & #function. Swift is becoming Twitter now! I, for one, am very excited about this 😜

Joking aside, these are actually pretty cool and when memorized, can save you a lot of time. They are called special literal expressions. Fairly self-explanatory if you ask me; however, I will try to shed some light on them either way.

Much like numbers (and anything contained in quotes) are number and string literals, respectively, #file, #line, #column, & #function are also literals; as a result, they can be used like any normal literal. As for their return values, here's a nifty table:

Personally, my favorite one to use is the #function literal. It's pretty useful for debugging purposes. For example, how many times have you asked yourself, "Self? Can you tell me where the hell this function is getting called from? It's not supposed to, you know. That's gotta be the bug I'm seeing".

Well, worry no more! When placed as the default value of a parameter, the #function literal will print the name of the function that called through to the function it's a part of like so:

func wreakHavocOnHumanity(krakenArmy: [Kraken], callingFunction: String = #function) {
    //There's a bug! There's too much havoc being wreaked!
    //Let's figure out who all is calling this function so we can
    //fix the bug! We absolutely need to make sure that the 
    //appropriate amount of havoc be wreaked.
    print("Name of Function who called \(#function): \(callingFunction).")
}

func startTheWar() {
    wreakHavocOnHumanity(krakenArmy)
}

func startEatingDinner(platter: Human) {
    wreakHavocOnHumanity(krakenArmy)
}

startTheWar() //prints "Name of Function who called wreakHavocOnHumanity: startTheWar."
startEatingDinner(human) //prints "Name of Function who called wreakHavocOnHumanity: startEatingDinner."

Back to Top

Loop Labels (extending break and continue)

Don't knock this one quite yet. At first look, you may be like, "Dammit Hector. I know what breaks and continues are. Stop wasting my time."

Rudeness aside, Swift takes the break and continue keywords a step further and gives you the ability to label them. Sometimes, you may find that you have nested loop logic that kind of looks like this:

for section in sections {
    var foundTheMagicalRow = false
    for row in rows {
        if row.isMagical {
            foundTheMagicalRow = true
            break
        }
    }
    if foundTheMagicalRow {
        //We found the magical row! 
        //No need to continue looping through our sections now.
        break
    }
}

Using labels for your loops, you can shorten this code quite a bit. By using a label, you can indicate a specific loop to break or continue. Now here is some pretty code for you which is the exact same as the code above:

sectionLoop: for section in sections {
    rowLoop: for row in rows {
        if row.isMagical {
            break sectionLoop
        }
    }
}

Back to Top

Type Omission

Type Omission is pretty damn cool. By taking advantage of type inference in Swift, we can actually use the sugar syntax of enums with variables and even functions!

The rule of thumb is this:

Your function or variable must be a static member of a type that returns an instance of that type.

The most prominent example of this is UIKit's UIColor class. Looking at the UIColor header in Xcode we see something like this:

@available(iOS 2.0, *)
public class UIColor : NSObject, NSSecureCoding, NSCopying {
    // Some convenience methods to create colors.  These colors will be as calibrated as possible.
    // These colors are cached.
    public class func blackColor() -> UIColor // 0.0 white 
    public class func darkGrayColor() -> UIColor // 0.333 white 
    public class func lightGrayColor() -> UIColor // 0.667 white 
    public class func whiteColor() -> UIColor // 1.0 white 
    public class func grayColor() -> UIColor // 0.5 white 
    public class func redColor() -> UIColor // 1.0, 0.0, 0.0 RGB 
    public class func greenColor() -> UIColor // 0.0, 1.0, 0.0 RGB 
    public class func blueColor() -> UIColor // 0.0, 0.0, 1.0 RGB 
    public class func cyanColor() -> UIColor // 0.0, 1.0, 1.0 RGB 
    public class func yellowColor() -> UIColor // 1.0, 1.0, 0.0 RGB 
    public class func magentaColor() -> UIColor // 1.0, 0.0, 1.0 RGB 
    public class func orangeColor() -> UIColor // 1.0, 0.5, 0.0 RGB 
    public class func purpleColor() -> UIColor // 0.5, 0.0, 0.5 RGB 
    public class func brownColor() -> UIColor // 0.6, 0.4, 0.2 RGB 
    public class func clearColor() -> UIColor // 0.0 white, 0.0 alpha 
}

Each one of those class functions fulfill our rule of thumb. Being class functions, they are static members of the UIColor type since they can be called directly on UIColor. Because they return an instance of UIColor, they fulfill the second part of our rule of thumb! This allows us to write code that looks like this:

func createKrakenWithSkinColor(skinColor: UIColor) -> Kraken {
    let kraken = Kraken()
    kraken.skinColor = skinColor
    return kraken
}

//Instead of calling our function like this:
let kraken = createKrakenWithSkinColor(UIColor.purpleColor())

//We can omit the UIColor type like this:
let kraken = createKrakenWithSkinColor(.purpleColor())

As you can see in the second code example above, we no longer have to write "UIColor" when accessing the purpleColor() function. Swift knows that our createKrakenWithSkinColor function accepts an instance of UIColor so it can infer the type for us!

We can do the same thing with variables as well:

class Kraken {
    static let theMotherOfAllKrakens = Kraken()
}

class Human {
    func attack(attackedKraken: Kraken) {
        //...
    }
}

//The humans are fed up. It's time to strike back and hit 'em where it hurts
for human in humansThatHaveLostALovedOneToAKraken {
    human.attack(.theMotherOfAllKrakens)
}

As you can see in the for loop above, we don't have to access the mother of all Krakens by calling Kraken.theMotherOfAllKrakens. Since theMotherOfAllKrakens is a static variable on Kraken and it's of type Kraken, then it fulfills our rule of thumb.

This rule of thumb is actually how enums work to give us our beloved enum sugar syntax. Because each case of an enum is a static member of that enum type and each case is an instance of that enum, Swift allows us to use it everywhere without spelling out the name of that enum!

Back to Top

Conclusion

For the most part, these things are just good to know but I know that for some of you out there, you can appreciate a little bit of optimization code now and then. Plus, you can always say you knew about such and such before it was cool in Swift. You may not use these in your day-to-day code but it's always nice to see something you probably didn't know. I definitely enjoyed writing this post because, on my search for obscure things in Swift, even I learned a thing or two. And hey, you might even have a Hipster moment one day and tell someone that you knew that thing in Swift before it was cool one day like a true hipster. And with that, I'll leave you guys alone. As always, happing coding fellow nerds!