BENEDIKT TERHECHTE

This is my research notebook. I'm an OSX / iOS indie developer. After 8 years of Objective-C I really enjoy Swift nowadays. Trying to publish all my research on Development, Swift & other technologies here.

Tue, 2 Feb 2016 #

Hirundo: Comfortably follow Swift Mailing Lists on OSX

If you're interested in Swift, the mailing lists are a fantastic resource. Swift-Evolution discusses the future of the language and includes many interesting messages about the shape that the language may become. Following it also really helps understanding the bigger idea behind many of Swift's most interesting features. Swift-Dev, on the other hand, goes down into the details of how Swift works internally. If that's not your thing, there's Swift-Users which covers questions and discussions about Swift from a user / programmers point of view.

Following those lists is not only useful, but also brings tremendous benefits. However, following them is also kinda hard:

  • The web archive is not easy to navigate
  • When you subscribe to a list you're bound to the UI of a mailing list / your Mail app
  • You can't see any messages posted before you subscribed
  • Many convenience functions (Bookmarks, Muting, etc) are not available

This bugged me. I wanted to be able to follow the discussions there, but I'd rather have a nice UI for them. So over Christmas I started working on a small app to solve this dilemma.

1 Enter Hirundo

Hirundo is the result of this (Written in Swift, of course). The word is latin and means Sparrow or Swift, so I thought it'd be a nice fit and it sounds cool. There's also an accompanying website for the app under stylemac.com/hirundo.

The app is currently in beta as I'm trying to iron out the remaining bugs. I'm already very happy with how it turned out and with the current set of implemented features. Among other things, the app supports:

  • Follow multiple Swift lists
  • Browse and search everything posted to the lists
  • Detailed search facilities over all messages in all lists
  • You can mute threads so that they don't appear in the lists anymore
  • If you are subscribed to a list, Hirundo will open Mail.app with reply headers set
  • Read messages from selected authors, search for authors, or even manage favorite authors
  • Sort messages by various properties, including a Rank showcasing the most discussed threads
  • Messages are threaded, you can fold them or collapse them
  • Bookmark any message or thread into multiple folders and revisit them later
  • Reply to threads or start new threads

Download it here and give it a try.

2 Building it

Writing the app took longer than I initially expected. I sometimes tend to be naive about technical limitations and so I just started working on this app without really assessing the difficulty of implementing it. The biggest issue was that the Swift mailing list data is not available via a REST API or something which else that one could query. There're only two ways of accessing the data:

2.1 Parsing the HTML archives

However this has several drawbacks. It requires a ton of HTTP requests, and it is very slow crawling the server for them. Those HTML pages use very simple, non-semantic HTML which makes it difficult and error prone to parse them correctly. Even worse, it lacks certain data which is required to properly establish the message tree afterwards.

2.2 Parsing the mailing archives

This is what I used. The archives are in the Unix mbox format so there's a way better chance of parsing them properly. They also contain all the information required to build up the message threads afterwards. I decided to use MailCore 2 for the actual parsing of the mails in the mbox so that I'd not need to reimplement another RFC2822 parser. However, a couple of small differences between RFC2822 and the mbox format generated by pipermail1 required additional effort in order to properly format the mbox contents so that MailCore could read them. The messages are then read, parsed, converted, and finally placed in Core Data.

3 Real Time Messages

After playing with the app for a while, I realized that the mailing list archives were not updated in real time. Instead, the compressed archives are only generated once a day. This makes the whole approach obsolete for actual following the discussions. This was also when I realized I should have invested more time up front researching this. Since the HTML was not feasible for import I was at an impasse. The solution, it seemed, was to host the temporary real time messages myself.

The next step (again, this took way longer than expected) was setting up an smtp email server which receives mails to mailing lists that I subscribe it to, and writes them out into the mbox format. A small webserver then offers those files as temporary caches of current mailing list activity. As soon as the official mailing list archives are updated, the cached ones are deleted2. If you're running Little Snitch this is what happens when you see Hirundo download data from hirundo-lists.stylemac.com.

4 Replying to Messages or creating Threads

When you click reply or new Hirundo opens your standard mail client with a mailto: call embedding all required mail headers for a proper reply. However Mail.app does not respect one of the required headers (In-Reply-To) so I had to use the (References) alternative header instead. That is a working solution but not optimal as it makes it more difficult for Pipermail (the mailing list) to properly thread your reply to the correct location. Other mail clients (such as Thunderbird) don't seem to have this problem. A future solution would be to send the mail directly from within Hirundo.

5 Building the UI

Once that finally worked, I started working on the UI of the app. I decided to limit it to 10.11 El Capitan, so that I could play around with all the new and exciting technologies released last WWDC. As it happens, I haven't even reached 1.0 and there's already a list of upcoming refactorings I'd like to perform as some initial design decisions were not as good as I thought they'd be in hindsight.

6 Mac App Development

I wrote a couple of interesting small classes for this project, and I'll spend the next posts on appventure building a simple Mac App based on some of the Hirundo code. There's currently a certain lack of Swift OSX development information, and I'd like to fill this void a bit.

Footnotes:

1

The mailing software used by the Swift Mailing Lists

2

There's a certain chance that, given the right timing, a message may not end up in Hirundo until one day later

If you read this far, you should follow me (@terhechte)
on Twitter


    Tue, 8 Dec 2015 #

    Swift Package Manager: Create and Use a X11 package on Linux

    This post is also available in 🇨🇳Chinese Thanks to SwiftGG

    Now that Swift is open source, many interested users might be installing and testing it on their Linux systems. However, currently the Foundation framework is still very much a work-in-progress so if you're interested in developing more than a simple shell app, you'll need to link against existing Linux libraries like GTK, Cairo, or libpng in order to gain access to useful functionality.

    I just finished implementing a simple Swift app which links against X11, the most basic Unix UI library 1. In this short tutorial, I'll show how to write a simple X11 app, and how you can utilize this to link against other libraries.

    In the process, we'll also use the new Swift package manager to create a simple re-usable package for the X11 library.

    Here's a screenshot of the finished app in action2:

    screenshot.png

    1 Swift Packages

    Before we write our actual X11 app, we need to define a Swift package which defines the links against the X11 library. Once this is done, we can easily share this package with other users, or re-use it in other projects. We have to differentiate between defining a package and using a package. Let's start with the first and then see how we can use that package.

    1.1 Defining a package

    Create a new folder which will host our package. Since we're linking against a C library, we follow the guidance of the Swift Package Manager documentation and prefix our library with the letter C3. We'll name our library CX11.swift

    mkdir CX11.swift
    

    In our case, we want to link against an existing C API and we do not intend to write any Swift wrapper code. Linking against C libraries and headers is achieved via the module.modulemap file which contains the necessary directives for the Swift compiler to perform the correct linking. The documentation for the modulemap syntax can be found here. We create the module map file, and edit the contents (via an editor of your choice, in this case we're using nano):

    touch CX11.swift/module.modulemap
    nano CX11.swift/module.modulemap
    

    X11 is a huge library with a lot of functionality. You can see the contents if you head over to /usr/include/X11. For our example, we don't need to include all the header files in there, instead we really only need two of them: Xlib.h and X.h. For different other libraries, you may need to include more headers. There is a convenient way to include all the headers in a directory which I'll point out below. Apart from including the headers, we also need to tell Swift which library to link against. We're using the link keyword for that. Our modulemap looks like this:

    module CX11 [system] {
      module Xlib {
    	  header "/usr/include/X11/Xlib.h"
      }
      module X {
    	  header "/usr/include/X11/X.h"
      }
      link "X11"
    }
    

    We're naming our module CX11 and we're creating two submodules. One for the Xlib and one for X. Each submodule defines the header it needs to import. Finally, we're linking against libx11 via the link statement.

    But what if we have not just one header file, but many of them. Module maps allow you to define an umbrella header or an umbrella directory.

    Umbrella Header This is a header that contains just references to other headers (via #include) commands. A good example is <Cocoa/Cocoa.h> or <Foundation/Foundation.h> or <gtk/gtk.h>. Umbrella headers are defined via the umbrella keyword:

    umbrella header "/usr/include/gtk/gtk.h"
    

    Umbrella Directory Sometimes you have a directory of headers but no umbrella header. In this case you just point Swift to the directory of headers:

    umbrella "/usr/include/X11/"
    

    In addition to the modulemap, we'll also need a Package.swift file, otherwise building will fail. This file can be empty though:

    touch CX11.swift/Package.swift
    

    The Swift package manager uses Git and Git Tags in order to manage packages. So before we're done, we need to create a Git repository for our Package, add all the files, and create a version tag. This is fairly easy though:

    cd CX11.swift
    git init
    git add .
    git commit -m "Initial Import"
    git tag 1.0.0
    cd ..
    

    The commands above go into the folder, create a new Git repository, add all the files to it, create a first commit, and finally add a version tag (1.0.0) for this commit.

    That's it, our package is defined, but how do we use it?

    1.2 Using Packages

    In order to use a package, we need to define a Package.swift file which will tell Swift which packages we intend to import for our project. But first, we need to create a directory for our project.

    mkdir swift-x11
    touch swift-x11/Package.swift
    touch swift-x11/main.swift
    

    Keep in mind that (for this example to work) the swift-x11 folder has to be next to the CX11.swift folder. I.e.:

    ls -l
    CX11.swift
    swift-x11
    

    Before we start writing the actual Swift code to interact with X11, we need to tell our swift-x11 project how to import the CX11 package. This is done, as explained below, via the swift-x11/Package.swift:

    import PackageDescription
    
    let package = Package(
      dependencies: [
        .Package(url: "../CX11.swift", majorVersion: 1)
      ]
    )
    

    This tells Swift that the package we intend to use is located in the ../CX11.swift folder.

    The url (as the name suggests) does not need to be a local one. I've uploaded my own CX11.swift to GitHub, and you could alternatively link directly to the GitHub version as follows:

    import PackageDescription
    
    let package = Package(
      dependencies: [
        .Package(url: "https://github.com/terhechte/CX11.swift.git", majorVersion: 1)
      ]
    )
    

    2 Using X11

    Now that we defined an X11 package, and set up the package manager definitions, we want to write our first X11 application.

    One issue which I could not solve is that macro definitions in the X11 header file are not imported into Swift. The Xlib.h defines many shortcut macros like:

    #define RootWindow(dpy, src) (ScreenOfDisplay(dpy, src)->root)
    #define ScreenOfDisplay(dpy, scr)(&((_XPrivDisplay)dpy)->screens[scr])
    

    As these were not imported, I decided instead to always write out the contents of the macro. All the code below has to be put into the main.swift file. You can also see the finished version here on GitHub. Please note that this is a simple and non-memory-safe example. This mostly serves to explain how to use C libraries under Linux. Also, my X11 knowledge is rather limited. I did Linux X11 programming more than 10 years ago and forgot most of it, so there may be factual errors in the explanation below. If you find them, feel free to open a PR on this repo :)

    We begin by importing the CX11 library which we defined above:

    import CX11.Xlib
    import CX11.X
    

    2.1 Setting up state

    After this, we have to define a couple of variables.

    • We need the X11 display (i.e. roughly speaking the X11 server connection). This will be the d variable
    • We need a placeholder for the X11 window which we create. This will be the w variable.
    • We also need to set aside a bit of memory for the X11 Server to store X11 input events. This is the e variable.
    • We should also already store the text which we want to display in our window. This is the msg variable
    • We need a place to store the current X11 screen (a X11 Display can have multiple screens). This will be the s variable.
    • Finally, we need a pointer to the X11 root window, which houses the other windows. This is the rootWindow variable.
    // The X11 Display
    var d: _XPrivDisplay
    
    // The window which we will create
    var w: Window
    
    // The events which X11 generates for us will be stored here
    var e = UnsafeMutablePointer<_XEvent>.alloc(1)
    
    // The text to display
    var msg = "Hello Swift World"
    
    // A pointer to the current X11 Screen
    var s: UnsafeMutablePointer<Screen>
    

    Now that we defined our variables, we need to open our connection to the X11 Server. However, as users can also run this app when no X server is running (i.e. in console mode) we need to make sure that the connection succeeded:

    d = XOpenDisplay(nil)
    if d == nil {
    	fatalError("cannot open display")
    }
    

    After we opened the display, we'd like to get the current default screen as well as the current root window. The RootWindow macro is not available4, so we will access the memory section of the C struct directly. However, as the current screen s is a UnsafeMutablePointer, we need to add the memory property in order to access the root instance.

    // Get the default screen
    s = XDefaultScreenOfDisplay(d)
    
    // And the current root window on that screen
    let rootWindow = s.memory.root
    

    2.2 Creating a Window

    Finally we have everything in place to create our own window and place it on the screen. We're using the XCreateSimpleWindow function for that. The function has the following parameters:

    XCreateSimpleWindow(Display *display, Window parent, int x, int y, 
      unsigned int width, unsigned int height, unsigned int border_width, 
      unsigned long border, unsigned long background);
    

    border and background are color values. In order to not think about color creation, we will simply pass in a reference to the default black and white colors which are defined on the current screen. We have to use the .memory property again.

    // Create our window
    w = XCreateSimpleWindow(d, rootWindow, 10, 10, 200, 100, 1, 
      s.memory.black_pixel, s.memory.white_pixel)
    

    This will create a new window on the rootWindow position 10/10 of width 200 and height 100. The borders will be black, the background will be white.

    2.3 Input Events

    Of course, we also want to receive input events from the Xserver. In our case we'd like to know when the window is being displayed so that we can draw it, and we'd like to know when the user pressed a key so that we can quit the app. The first event is the Expose event, the second one is the KeyPress event. Receiving events works by registering event masks via the XSelectInput function:

    XSelectInput(d, w, ExposureMask | KeyPressMask)
    

    Now that we created our window, we want to display it. This is done via the XMapWindow function:

    XMapWindow(d, w)
    

    2.4 Event Loop

    Finally we do have everything in place to run our event loop while the window is being displayed. For this, we're using a while loop which continously pulls the XNextEvent function to get new X11 events. Then, we'll test the event to see whether it is a Expose or a KeyPress event5. We're testing the events using the swift switch statement:

    loop: while true {
    
      // Wait for the next event
      XNextEvent(d, e)
    
      switch e.memory.type {
        // The window has to be drawn
        case Expose:
        // draw a small black rectangle
        XFillRectangle(d, w, s.memory.default_gc, 20, 20, 10, 10) 
        // draw the text
        XDrawString(d, w, s.memory.default_gc, 10, 70, msg, Int32(msg.characters.count)) 
    
        // The user did press a key
        case KeyPress:
        break loop
    
        // We never signed up for this event
        default: fatalError("Unknown Event")
    
      }
    }
    

    Our e event structure is - again - a UnsafeMutablePointer, so we have to access the actual structure via the memory property. The Expose event means that the window is visible, so we have to re-draw it. Our drawing is very simple: We're using the XFillRectangle call to draw a small black box, and the XDrawString call to draw our initial msg text in the window at position 10, 70. Please note that I don't know whether X11 expects unicode or ascii, so the Int32(msg.characters.count) is probably wrong, but it works in this example.

    The other event, KeyPress allows us to break the outer while loop and quit the app once the user enters a key.

    3 Running It

    To use this, simply check out the repo (preferrably on Linux) and do the following in the folder:

    swift build
    

    This will clone the CX11.swift package and build the binary in the .build/debug folder.

    Run it via:

    .build/debug/swift-x11-example
    

    This will execute the binary, and a small X11 Window should appear on your desktop:

    screenshot.png

    4 Conclusion

    This was a very simple example of how to use Swift under Linux to write an X11 app. This will also work for all kind of other apps using other libraries, of course. This tutorial also explained how the new Swift Package manager works by creating and using a simple X11 package.

    The full example of the X11 app can be found here.

    The full example of the X11 package can be found here.

    Footnotes:

    1

    I started with GTK3, but could not get that to work

    2

    Spectacular, isn't it ;)

    3

    "The convention we hope the community will adopt is to prefix such modules with C and to camelcase the modules as per Swift module name conventions. Then the community is free to name another module simply JPEG which contains more “Swifty” function wrappers around the raw C interface."

    4

    See above, I couldn't figure out why

    5

    Remember those are the only events we signed up for

    If you read this far, you should follow me (@terhechte)
    on Twitter


      Mon, 30 Nov 2015 #

      Reduce all the things

      This post is also available in 🇨🇳Chinese Thanks to SwiftGG

      Even before Swift was released, iOS / Cocoa developers could use third party frameworks like ObjectiveSugar or ReactiveCocoa in order to gain functional programming constructs like map, flatMap or filter. With Swift, they have become first class language citizens. There are many advantages to using them over a standard for loop. They typically express your intent better, they require less code, and they can be chained together in order to build up complex logic in a clear way.

      In this post, I'd like to show another very cool functional addition to Swift which can sometimes be a better solution than map / filter constructs: reduce.

      1 A simple Problem

      Consider this problem: You're getting a list of persons from a JSON endpoint. You'd like to know the average age from all people living in California. The parsed data looks like this:

      let persons: [[String: AnyObject]] = [["name": "Carl Saxon", "city": "New York, NY", "age": 44],
       ["name": "Travis Downing", "city": "El Segundo, CA", "age": 34],
       ["name": "Liz Parker", "city": "San Francisco, CA", "age": 32],
       ["name": "John Newden", "city": "New Jersey, NY", "age": 21],
       ["name": "Hector Simons", "city": "San Diego, CA", "age": 37],
       ["name": "Brian Neo", "age": 27]]
      

      Note the last entry, which omits a city for the person in question. Those cases have to be silently ignored.

      The expected result in the example would be 3 persons , as we have three persons from California. Let's try to implement this in Swift in terms of flatMap and filter. The flatMap is used instead of map as flatMap automatically ignores empty optionals. So flatMap([0, nil, 1, 2, nil]) results in [0, 1, 2]. This eases the handling of persons without a proper city.

      func infoFromState(state state: String, persons: [[String: AnyObject]]) 
           -> Int {
          return persons.flatMap( { $0["city"]?.componentsSeparatedByString(", ").last })
      	   .filter({$0 == state})
      	   .count
      }
      infoFromState(state: "CA", persons: persons)
      //#+RESULTS:
      //: 3
      

      That's simple enough.

      However, now consider the following complication: You'd like to know how many of those persons live in California, and you'd like to know their average age. If we try upgrading the above example, we soon realize that his is a slightly harder problem. There are various solutions, but they all seem to not fit well with functional constructs. A loop-based approach feels much simpler.

      When we think about why this does fit, we realize it is because the shape of the data changes. map, flatMap, and filter all keep the shape of the data similar. Array goes in, array goes out. The amount and the contents of the array may change, but the array-shape stays. The problem above, however, requires us to change the shape to a struct or tuple with an Integer average and an Integer sum.

      These are the kind of problems where you can apply reduce.

      2 Reduce

      Reduce is sort of a generalized version of map, flatMap, or filter. The basic idea is to reduce a sequence into a different shape utilizing an accumulator that can keep incremental state. To do this, we hand the function a combinator closure/function/method which is called once for each item in the sequence. This may sound complicated but becomes really easy with a couple of examples.

      It is a method on SequenceType and looks like this (simplified):

      func reduce<T>(initial: T, combine: (T, Self.Generator.Element) -> T) -> T
      

      So we have an initial value, and we have a closure which expects us to return the same type as the initial value. The final value of the operation is also of the same type as the initial value.

      If we take a very simple reduce operation - adding up a list of integers, the evaluation will look like this:

      func combinator(accumulator: Int, current: Int) -> Int {
         return accumulator + current
      }
      [1, 2, 3].reduce(0, combine: combinator)
      // The following steps will be performed
      combinator(0, 1) { return 0 + 1 } = 1
      combinator(1, 2) { return 1 + 2 } = 3
      combinator(3, 3) { return 3 + 3 } = 6
      = 6
      

      The combinator function will be called once for each item in the list [1, 2, 3]. The state will be kept in the accumulator variable which is just an Integer.

      Let's start re-implementing some of our other, trusted, functional programming friends. In order to keep things simple for now, all these functions will operate on Int or Optional<Int>; i.e. we will ignore generics in here. Also, keep in mind that the implementations below exist to explain the behaviour of reduce. The native Swift implementations are usually much faster compared to the reduce versions below1. Reduce shines in a different set of problems, which will be explained further below.

      2.1 Map

      func rmap(elements: [Int], transform: (Int) -> Int) -> [Int] {
          return elements.reduce([Int](), combine: { (var acc: [Int], obj: Int) -> [Int] in
             acc.append(transform(obj))
             return acc
          })
      }
      print(rmap([1, 2, 3, 4], transform: { $0 * 2}))
      // [2, 4, 6, 8]
      

      This is a good example to understand the basics of reduce.

      • First, we're calling reduce on a sequence of elements elements.reduce....
      • Next, We're giving it the accumulator, i.e. an empty Int array, which will form or return type / result [Int]()
      • After that, we're handing in the combinator which takes two parameters. The first is the accumulator which we just provided acc: [Int], the second is the current object from our sequence obj: Int.
      • The actual code in the combinator is simple. We simply transform the obj and append it onto the accumulator. We then return the accumulator.

      This looks like much more code than just calling map. That's indeed true, but the version above is extra detailed in order to better explain how reduce works. We can simplify it.

      func rmap(elements: [Int], transform: (Int) -> Int) -> [Int] {
          return elements.reduce([Int](), combine: {$0 + [transform($1)]})
      }
      print(rmap([1, 2, 3, 4], transform: { $0 * 2}))
      // [2, 4, 6, 8]
      

      This still works fine. What happened here? We're using the convenient fact that in Swift, the + operator also works for two sequences. So [0, 1, 2] + [transform(4)] takes the left sequence and adds the right sequence, consisting out of the transformed element, to it.

      It should be noted that, as of right now, [1, 2, 3] + [4] is slower than [1, 2, 3].append(4). If you operate on huge lists, instead of using collection + collection, you should have a mutable accumulator and mutate it in place:

      func rmap(elements: [Int], transform: (Int) -> Int) -> [Int] {
          return elements.reduce([Int](), combine: { (var ac: [Int], b: Int) -> [Int] in 
      	ac.append(transform(b))
      	return ac
          })
      }
      

      In order to better understand reduce we will now go on and also implement flatMap and filter.

      func rflatMap(elements: [Int], transform: (Int) -> Int?) -> [Int] {
          return elements.reduce([Int](), 
             combine: { guard let m = transform($1) else { return $0 } 
      		  return $0 + [m]})
      }
      print(rflatMap([1, 3, 4], transform: { guard $0 != 3 else { return nil }; return $0 * 2}))
      // [2, 8]
      

      The main difference is that we're adding a guard to make sure the optional contains a value.

      2.2 Filter

      func rFilter(elements: [Int], filter: (Int) -> Bool) -> [Int] {
          return elements.reduce([Int](), 
             combine: { guard filter($1) else { return $0 } 
      		  return $0 + [$1]})
      }
      print(rFilter([1, 3, 4, 6], filter: { $0 % 2 == 0}))
      // [4, 6]
      

      Again, a simple operation. We're leveraging guard again to make sure our filter condition holds.

      Up until now, reduce may feel like a more complicated version of map or filter without any major advantages. However, the combinator does not need to be an array. It can be anything. This makes it easy for us to implement various reduction operations in a very simple way.

      3 Reduce Examples

      Let's start with a favorite of mine, the sum of a list of numbers:

      [0, 1, 2, 3, 4].reduce(0, combine: +)
      // 10
      

      + is a valid combinator function as it will just add the lhs and the rhs and return the result, which is specifically the requirement reduce has.

      Another example is building the product of a list of numbers:

      [1, 2, 3, 4].reduce(1, combine: *)
      // 24
      

      Or what about reversing a list:

      [1, 2, 3, 4, 5].reduce([Int](), combine: { [$1] + $0 })
      // 5, 4, 3, 2, 1
      

      Finally, something a tad more complicated. We'd like to partition a list based on a division criteria

      typealias Acc = (l: [Int], r: [Int])
      func partition(lst: [Int], criteria: (Int) -> Bool) -> Acc {
         return lst.reduce((l: [Int](), r: [Int]()), combine: { (ac: Acc, o: Int) -> Acc in 
            if criteria(o) {
      	return (l: ac.l + [o], r: ac.r)
            } else {
      	return (r: ac.r + [o], l: ac.l)
            }
         })
      }
      partition([1, 2, 3, 4, 5, 6, 7, 8, 9], criteria: { $0 % 2 == 0 })
      //: ([2, 4, 6, 8], [1, 3, 5, 7, 9])
      

      The most interesting thing we're doing above is using a tuple as the accumulator. As you'll find out, once you start trying to incorporate reduce into your daily work-flow, tuples are a great way of quickly combining related data during a reduce operation.

      4 Reduce vs. Chaining Performance

      Apart from the higher flexibility that reduce offers, it has another advantage: Oftentimes, chaining map and filter induces a performance penalty as Swift has to iterate over your collection multiple times in order to generate the required data. Imagine the following code:

      [0, 1, 2, 3, 4].map({ $0 + 3}).filter({ $0 % 2 == 0}).reduce(0, combine: +)
      

      Apart from being nonsensical, it is also wasting CPU cycles. The initial sequence will be iterated over 3 times. First to map it, then to filter it, and finally to sum up the contents. Instead, all of this can just as well be implemented as one reduce call, which greatly improves the performance:

      [0, 1, 2, 3, 4].reduce(0, combine: { (ac: Int, r: Int) -> Int in 
         if (r + 3) % 2 == 0 {
           return ac + r + 3
         } else {
           return ac
         }
      })
      

      Here's a quick benchmark of running both versions and the for-loop version below over an list with 100.000 items:

      var ux = 0
      for i in Array(0...100000) {
          if (i + 3) % 2 == 0 {
      	ux += (i + 3)
          }
      }
      
      For Loop: 0.030 seconds
      Reduce: 0.034 seconds
      Map/Filter: 0.072 seconds

      As you can see, the reduce version' performance is very close to the mutating for loop and more than twice as fast as the chaining operation.

      However, in other situations, chained operation can greatly outperform reduce. Consider the following example:

      Array(0...100000).map({ $0 + 3}).reverse().prefix(3)
      // 0.027 Seconds
      
      Array(0...100000).reduce([], combine: { (var ac: [Int], r: Int) -> [Int] in
          ac.insert(r + 3, atIndex: 0)
          return ac
      }).prefix(3)
      // 2.927 Seconds
      

      Here, we have a stark performance difference of 0.027s for the chained operation vs. 2.927s for the reduce operation, what's happening here?2

      foBrowsing on Reddit points out that reduce's semantics means that the parameters to the closure (if mutated) are copied once for every element in the underlying sequence. In our case, this means that the accumulator parameter ac will be copied for each item in our 0…100000 range. A better, more detailed explanation of this can be found in this Airspeedvelocity blog post.

      So, when you're replacing a set of operations with reduce, always keep mind whether reduction is indeed a good use case for the situation in question.

      We can now go back to our initial count & average problem and try to solve it with reduce.

      5 InfoFromState, take two

        func infoFromState(state state: String, persons: [[String: AnyObject]]) 
            -> (count: Int, age: Float) {
      
            // The type alias in the function will keep the code cleaner
            typealias Acc = (count: Int, age: Float)
      
            // reduce into a temporary variable
            let u = persons.reduce((count: 0, age: 0.0)) {
      	  (ac: Acc, p) -> Acc in
      
      	  // Retrive the state and the age
      	  guard let personState = (p["city"] as? String)?.componentsSeparatedByString(", ").last,
      		personAge = p["age"] as? Int
      
      	    // make sure the person is from the correct state
      	    where personState == state
      
      	    // if age or state are missing, or personState!=state, leave
      	    else { return ac }
      
      	  // Finally, accumulate the acount and the age
      	  return (count: ac.count + 1, age: ac.age + Float(personAge))
            }
      
        // our result is the count and the age divided by count
        return (age: u.age / Float(u.count), count: u.count)
      }
      print(infoFromState(state: "CA", persons: persons))
      // prints: (count: 3, age: 34.3333)
      

      As in earlier examples above, we're once again using a tuple to share state in the accumulator. Apart from that, the code is easy to understand.

      We also defined a typealias Acc within the func in order to simplify the type annotations a bit.

      6 Summary

      This was a short overview of the power behind the reduce method. It is particularly helpful if you end up chaining a lot of functional methods together, or when output shape of your data differs from the input shape. I'll end this post with more reduce examples to give you inspirations for various use cases where reduce can easily be applied:

      7 More Examples

      The following examples display additional reduce use cases. Keep in mind that they're educational in nature. I.e. they exist to stress the usage of reduce, not to be general solutions for your codebase. Most of the examples can be written in a better and faster way (i.e. by using extensions or generics). There are better implementations of these examples in various Swift libraries such as SwiftSequence or Dollar.swift

      7.1 Minimum

      Return the minimum entry in a given list. Obviously, [1, 5, 2, 9, 4].minElement() would be a better solution.

      [1, 5, 2, 9, 4].reduce(Int.max, combine: min)
      

      7.2 Unique

      Return a list with all duplicates removed. The better solution would be to use a Set.

      [1, 2, 5, 1, 7].reduce([], combine: { (a: [Int], b: Int) -> [Int] in
      if a.contains(b) {
         return a
      } else {
         return a + [b]
      }
      })
      // prints: 1, 2, 5, 7
      

      7.3 Group By

      Go over a list and return a new list with the previous list' items grouped by a discriminator function. The function in question needs to return a Hashable type so that we can differentiate keys. The order of the items will be preserved while the order of the groups won't necessarily be preserved.

      func groupby<T, H: Hashable>(items: [T], f: (T) -> H) -> [H: [T]] {
         return items.reduce([:], combine: { (var ac: [H: [T]], o: T) -> [H: [T]] in 
             let h = f(o)
             if var c = ac[h] {
      	   c.append(o)
      	   ac.updateValue(c, forKey: h)
             } else {
      	   ac.updateValue([o], forKey: h)
             }
             return ac
         })
      }
      print(groupby([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], f: { $0 % 3 }))
      // prints: [2: [2, 5, 8, 11], 0: [3, 6, 9, 12], 1: [1, 4, 7, 10]]
      print(groupby(["Carl", "Cozy", "Bethlehem", "Belem", "Brand", "Zara"], f: { $0.characters.first! }))
      // prints: ["C" : ["Carl" , "Cozy"] , "B" : ["Bethlehem" , "Belem" , "Brand"] , "Z" : ["Zara"]]
      

      7.4 Interpose

      This function returns the given items, with element inserted between every count items. The implementation below makes sure that the elements are only interposed and not appended at the end.

      func interpose<T>(items: [T], element: T, count: Int = 1) -> [T] {
         typealias Acc = (ac: [T], cur: Int, cnt: Int)
         return items.reduce((ac: [], cur: 0, cnt: 1), combine: { (a: Acc, o: T) -> Acc in 
             switch a {
      	  // the last item will not have any interposition
      	  case let (ac, cur, _) where (cur+1) == items.count: return (ac + [o], 0, 0)
      	  // interpose
      	  case let (ac, cur, c) where c == count:
      	     return (ac + [o, element], cur + 1, 1)
      	  // next
      	  case let (ac, cur, c):
      	     return (ac + [o], cur + 1, c + 1)
             }
         }).ac
      }
      print(interpose([1, 2, 3, 4, 5], element: 9))
      // : [1, 9, 2, 9, 3, 9, 4, 9, 5]
      print(interpose([1, 2, 3, 4, 5], element: 9, count: 2))
      // : [1, 2, 9, 3, 4, 9, 5]
      

      7.5 Interdig

      This function allows you to combine two sequences by alternately selecting elements from each.

      func interdig<T>(list1: [T], list2: [T]) -> [T] {
         return Zip2Sequence(list1, list2).reduce([], combine: { (ac: [T], o: (T, T)) -> [T] in 
      	return ac + [o.0, o.1]
         })
      }
      print(interdig([1, 3, 5], list2: [2, 4, 6]))
      // : [1, 2, 3, 4, 5, 6]
      

      7.6 Chunk

      This function returns self, broken up into non-overlapping arrays of length n:

      func chunk<T>(list: [T], length: Int) -> [[T]] {
         typealias Acc = (stack: [[T]], cur: [T], cnt: Int)
         let l = list.reduce((stack: [], cur: [], cnt: 0), combine: { (ac: Acc, o: T) -> Acc in
            if ac.cnt == length {
      	  return (stack: ac.stack + [ac.cur], cur: [o], cnt: 1)
            } else {
      	  return (stack: ac.stack, cur: ac.cur + [o], cnt: ac.cnt + 1)
            }
         })
         return l.stack + [l.cur]
      }
      print(chunk([1, 2, 3, 4, 5, 6, 7], length: 2))
      // : [[1, 2], [3, 4], [5, 6], [7]]
      

      This function uses a more complicated accumulator consisting out of a stack, the current list, and the count.

      8 Changes

      12/01/2015

      • Fixed the rFlatMap type signature
      • Added additional explanations for the code examples
      • Fixed issue where performance differences were attributed to laziness

      Footnotes:

      2

      In an earlier version of this post I was falsely assuming Swift's laziness feature to be the culprit of the difference. Thanks to this Reddit thread for pointing out my mistake

      If you read this far, you should follow me (@terhechte)
      on Twitter


        Sat, 24 Oct 2015 #

        The Swift Reflection API and what you can do with it

        This post is also available in 🇨🇳Chinese Thanks to SwiftGG

        Even though Swift stresses strong types, compile time safety, static dispatch it still offers a Reflection mechanism as part of the standard library. You may already have seen it in various blog posts or projects like here (Tuples), here (Midi Packets) or here (Core Data). Maybe you're interested in using in one of your projects, or you may want to better understand the problem domains on which reflection can be applied. This is an overview of the possibilities of the Swift Reflection API based a talk I held recently at the Macoun conference in Frankfurt, Germany.

        1 API Overview

        The best understanding of the topic can be achieved by having a look at the API to see what it offers us.

        1.1 Mirrors

        Swift's reflection capabilities are based around a struct called Mirror. You create a mirror for a particular subject and the mirror will then let you query it.

        Before we do that, let's define a simple data structure that we can use as our subject.

        import Foundation.NSURL
        
        public class Store {
            let storesToDisk: Bool = true
        }
        public class BookmarkStore: Store {
            let itemCount: Int = 10
        }
        public struct Bookmark {
           enum Group {
              case Tech
              case News
           }
           private let store = {
               return BookmarkStore()
           }()
           let title: String?
           let url: NSURL
           let keywords: [String]
           let group: Group
        }
        
        let aBookmark = Bookmark(title: "Appventure", url: NSURL(string: "appventure.me")!, keywords: ["Swift", "iOS", "OSX"], group: .Tech)
        

        1.2 Creating a Mirror

        The easiest way of creating a mirror is the reflecting initializer:

        public init(reflecting subject: Any)
        

        Lets use it with our aBookmark struct:

        let aMirror = Mirror(reflecting: aBookmark)
        print(aMirror)
        // prints : Mirror for Bookmark
        

        So this creates a Mirror for Bookmark. As you can see, the type of the subject is Any. This is the most general type in Swift. Anything under the Swift Sun is at least of type Any 1. So this makes the mirror compatible with struct, class, enum, Tuple, Array, Dictionary, set, etc.

        There are three additional initializers in the Mirror struct, however those are mostly used for circumstances where you'd want to provide your own, custom mirror. We will explain those additional initializers below when we discuss custom mirrors.

        1.3 What's in a Mirror

        The Mirror struct contains several types to help you identify the information you'd like to query.

        The first one is the DisplayStyle enum which tells you the type of the subject:

        public enum DisplayStyle {
            case Struct
            case Class
            case Enum
            case Tuple
            case Optional
            case Collection
            case Dictionary
            case Set
        }
        

        Those are the supported types of the reflection API. As we saw earlier, reflection only requires an Any type, and there're many things in the Swift standard library that are of type Any but aren't listed in the DisplayStyle enum above. What happens when you try to reflect over one of those, say a closure?

        let closure = { (a: Int) -> Int in return a * 2 }
        let aMirror = Mirror(reflecting: closure)
        

        In this case, you'd get a mirror, but the DisplayStyle would be nil 2

        There's also a typealias for the child elements of a Mirror:

        public typealias Child = (label: String?, value: Any)
        

        So each child consists out of an optional label and a value of type Any. Why would the label be an Optional? If you think about it, it makes sense, not all of the structures that are supported by reflection have children with names. A struct has the property's name as the label, but a Collection only has indexes, not names. Tuples are a little bit special. In Swift values in tuple could have optional labels. Doesn't matter if value in tupple is labeled or not, in reflection tuple will have labels ".0", ".1" and so on.

        Next up is the AncestorRepresentation enum 3:

        public enum AncestorRepresentation {
            /// Generate a default mirror for all ancestor classes.  This is the
            /// default behavior.
            case Generated
            /// Use the nearest ancestor's implementation of `customMirror()` to
            /// create a mirror for that ancestor.      
            case Customized(() -> Mirror)
            /// Suppress the representation of all ancestor classes.  The
            /// resulting `Mirror`'s `superclassMirror()` is `nil`.
            case Suppressed
        }
        

        This enum is used to define how superclasses of the reflected subject should be reflected. I.e. this is only used for subjects of type class. The default (as you can see) is that Swift generates an additional mirror for each superclass. However, if you need more flexibility here, you can use the AncestorRepresentation enum to define how superclasses are being mirrored. We will have a look at that further below.

        1.4 How to use a Mirror

        So we have our aMirror instance variable that reflects our aBookmark of type Bookmark subject. What do we do with it?

        These are the available properties / methods on a Mirror:

        • let children: Children: The child elements of our subject
        • displayStyle: Mirror.DisplayStyle?: The display style of the subject
        • let subjectType: Any.Type : The type of the subject
        • func superclassMirror() -> Mirror?: The mirror of the subject's superclass

        In the next step, we will analyze each of these.

        1.4.1 displayStyle

        This is easy. It will just return a case of the DisplayStyle enum. If you're trying to reflect over an unsupported type, you'll get an empty Optional back (as explained above).

        print (aMirror.displayStyle)
        // prints: Optional(Swift.Mirror.DisplayStyle.Struct)
        

        1.4.2 children

        This returns a AnyForwardCollection<Child> with all the children that the subject contains. Children are not limited to entries in an Array or Dictionary. All properties of a struct or class, for example, are also children returned by this property. The protocol AnyForwardCollection means that this is a collection type with indices that support forward traversal.

        for case let (label?, value) in aMirror.children {
            print (label, value)
        }
        //prints:
        //: store main.BookmarkStore
        //: title Optional("Appventure")
        //: url appventure.me
        //: keywords ["Swift", "iOS", "OSX"]
        //: group Tech
        

        1.4.3 SubjectType

        This is the type of the subject:

        print(aMirror.subjectType)
        //prints : Bookmark
        print(Mirror(reflecting: 5).subjectType)
        //prints : Int
        print(Mirror(reflecting: "test").subjectType)
        //prints : String
        print(Mirror(reflecting: NSNull()).subjectType)
        //print : NSNull
        

        However, the Swift documentation has the following to say:

        This type may differ from the subject's dynamic type when self is the superclassMirror() of another mirror.

        1.4.4 SuperclassMirror

        This is the mirror of the superclass of our subject. If the subject is not a class, this will be an empty Optional. If this is a class-based type, you'll get a new Mirror:

        // try our struct
        print(Mirror(reflecting: aBookmark).superclassMirror())
        // prints: nil
        // try a class
        print(Mirror(reflecting: aBookmark.store).superclassMirror())
        // prints: Optional(Mirror for Store)
        

        2 Practical Example

        2.1 Structs to Core Data

        Imagine we're working at the newest, hot, tech startup: Books Bunny. We offer an Artificial Intelligence with a browser plugin that automatically analyses all the sites that the user visits and automatically bookmarks the relevant urls.

        It's 2016, Swift is already open source, so our server backend is obviously written in Swift. Since we have millions of site visits active in our system at a time, we'd like to use structs for the analysis part of each site that a user visits. However, if our AI decides that this is worthy of a bookmark, we'd like to use CoreData to store this type in a database.

        Now, we don't want to write custom serialization to Core Data code whenever we introduce a new struct. Rather, we'd like to develop this in a way so that we can utilize it for all future structs we develop.

        So, how do we do that?

        2.2 A Protocol

        Remember, we have a struct and want to automatically convert this to NSManagedObject (Core Data).

        If we want to support different structs or even types, we can implement this as a protocol and then make sure our desired types conform to it. So which functionality should our imaginary protocol offer?

        • First, it should allow us to define the name of the Core Data Entity that we want to create
        • Second, it should have a way to tell it to convert itself to an NSManagedObject

        Our protocol could look something like this:

        protocol StructDecoder {
            // The name of our Core Data Entity
            static var EntityName: String { get }
            // Return an NSManagedObject with our properties set
            func toCoreData(context: NSManagedObjectContext) throws -> NSManagedObject
        }
        

        The toCoreData method uses the new Swift 2.0 exception handling to throw an error, if the conversion fails. There're several possible error cases, which are outlined in the ErrorType enum below:

        enum SerializationError: ErrorType {
            // We only support structs
            case StructRequired
            // The entity does not exist in the Core Data Model
            case UnknownEntity(name: String)
            // The provided type cannot be stored in core data
            case UnsupportedSubType(label: String?)
        }
        

        We have three error cases that our conversion has to look out for. The first one is that we're trying to apply it to something that is not a struct. The second is that the entity we're trying to create does not exist in our Core Data Model. The third is that we're trying to write something into Core Data which can not be stored there (i.e. an enum).

        Let's create a struct and add protocol conformance:

        2.3 Bookmark struct

        struct Bookmark {
           let title: String
           let url: NSURL
           let pagerank: Int
           let created: NSDate
        }
        

        Next, we'd like to implement the toCoreData method.

        2.4 Protocol Extension

        We could, of course, write this anew for each struct, but that's a lot of work. Structs do not support inheritance, so we can't use a base class. However, we can use a protocol extension to extend to all conforming structs:

        extension StructDecoder {
            func toCoreData(context: NSManagedObjectContext) throws -> NSManagedObject {
            }
        }
        

        As this extension is being applied to our conforming structs, this method will be called in the structs context. Thus, within the extension, self refers to the struct which we'd like to analyze.

        So, the first step for us is to create an NSManagedObject into which we can then write the values from our Bookmark struct. How do we do that?

        2.5 A Bit of Core Data

        Core Data is a tad verbose, so in order to create an object, we need the following steps:

        1. Get the name of the entity which we'd like to create (as a string)
        2. Take the NSManagedObjectContext, and create an NSEntityDescription for our entity
        3. Create an NSManagedObject with this information.

        When we implement this, we have:

        // Get the name of the Core Data Entity
        let entityName = self.dynamicType.EntityName
        
        // Create the Entity Description
        // The entity may not exist, so we're using a 'guard let' to throw 
        // an error in case it does not exist in our core data model
        guard let desc = NSEntityDescription.entityForName(entityName, inManagedObjectContext: context)
            else { throw UnknownEntity(name: entityName) }
        
        // Create the NSManagedObject
        let managedObject = NSManagedObject(entity: desc, insertIntoManagedObjectContext: context)
        

        2.6 Implementing the Reflection

        Next up, we'd like to use the Reflection API to read our bookmarks properties and write it into our NSManagedObject instance.

        // Create a Mirror
        let mirror = Mirror(reflecting: self)
        
        // Make sure we're analyzing a struct
        guard mirror.displayStyle == .Struct else { throw SerializationError.StructRequired }
        

        We're making sure that this is indeed a struct by testing the displayStyle property.

        So now we have a Mirror that allows us to read properties, and we have a NSManagedObject which we can set properties on. As the mirror offers a way to read all children, we can iterate over them and set the values. So let's do that.

        for case let (label?, value) in mirror.children {
            managedObject.setValue(value, forKey: label)
        }
        

        Awesome. However, if we try to compile this, it will fail. The reason is that setValueForKey requires an object of type AnyObject?, however our children property only returns a tuple of type (String?, Any) - i.e. our value is of type Any but we need an AnyObject. To solve this, we have to test the value for AnyObject conformance. This also means that we can throw an error if we receive a property with a type that does not conform to AnyObject (such as an enum, for example).

        let mirror = Mirror(reflecting: self)
        
        guard mirror.displayStyle == .Struct 
          else { throw SerializationError.StructRequired }
        
        for case let (label?, anyValue) in mirror.children {
            if let value = anyValue as? AnyObject {
        	managedObject.setValue(child, forKey: label)
            } else {
        	throw SerializationError.UnsupportedSubType(label: label)
            }
        }
        

        Now, our setValueForKey method will only be called if and only if the child is of type AnyObject.

        Now, the only thing left to do is return our NSManagedObject. The complete code looks like this:

        extension StructDecoder {
            func toCoreData(context: NSManagedObjectContext) throws -> NSManagedObject {
        	let entityName = self.dynamicType.EntityName
        
        	// Create the Entity Description
        	guard let desc = NSEntityDescription.entityForName(entityName, inManagedObjectContext: context)
        	    else { throw UnknownEntity(name: entityName) }
        
        	// Create the NSManagedObject
        	let managedObject = NSManagedObject(entity: desc, insertIntoManagedObjectContext: context)
        
        	// Create a Mirror
        	let mirror = Mirror(reflecting: self)
        
        	// Make sure we're analyzing a struct
        	guard mirror.displayStyle == .Struct else { throw SerializationError.StructRequired }
        
        	for case let (label?, anyValue) in mirror.children {
        	    if let value = anyValue as? AnyObject {
        		managedObject.setValue(child, forKey: label)
        	    } else {
        		throw SerializationError.UnsupportedSubType(label: label)
        	    }
        	}
        
        	return managedObject
            }
        }
        

        That's it. We're converting our struct to NSManagedObject.

        3 Performance

        So, how fast is this? Can this be used well in production? I did some testing:

        Create 2000 NSManagedObjects

        Native: 0.062 seconds
        Reflection: 0.207 seconds

        Native, here, means creating an NSManagedObject and setting the property values via setValueForKey. If you create a NSManagedObject subclass within Core Data and set the values directly on the properties (without the dynamic setValueForKey overhead) this is probably even faster.

        So, as you can see, using reflection slows the whole process of creating NSManagedObjects down by about 3.5x. This is fine when you're using this for a limited amount of items, or when you don't have to care about speed. However, when you need to reflect over a huge amount of structs, this will probably kill your app's performance.

        4 Custom Mirrors

        As we already discussed earlier, there're other options creating a Mirror. This is useful, for example, if you need to customize just how much of your subject can be seen with a mirror. The Mirror Struct has additional initializers for this.

        4.1 Collections

        The first special init is tailor-made for collections:

        public init<T, C : CollectionType where C.Generator.Element == Child>
          (_ subject: T, children: C, 
           displayStyle: Mirror.DisplayStyle? = default, 
           ancestorRepresentation: Mirror.AncestorRepresentation = default)
        

        Compared to the init(reflecting:) initializer above, this one allows us to define much more details about the reflection process.

        • It only works for collections
        • We can set the subject to be reflected and the children of the subject (the collection contents)

        4.2 Classes or Structs

        The second can be used for a class or a struct.

        public init<T>(_ subject: T, 
          children: DictionaryLiteral<String, Any>, 
          displayStyle: Mirror.DisplayStyle? = default, 
          ancestorRepresentation: Mirror.AncestorRepresentation = default)
        

        Interesting to note, here, is that you provide the children (i.e. properties) of your subject as a DictionaryLiteral which is a bit like a dictionary only that it can be used directly as function parameters. If we implement this for our Bookmark struct, it looks like this:

        extension Bookmark: CustomReflectable {
            func customMirror() -> Mirror {
        	let children = DictionaryLiteral<String, Any>(dictionaryLiteral: 
        	("title", self.title), ("pagerank", self.pagerank), 
        	("url", self.url), ("created", self.created), 
        	("keywords", self.keywords), ("group", self.group))
        
        	return Mirror.init(Bookmark.self, children: children, 
        	    displayStyle: Mirror.DisplayStyle.Struct, 
        	    ancestorRepresentation:.Suppressed)
            }
        }
        

        If we do another performance measurement now, there's even a slight improvement:

        Create 2000 NSManagedObjects

        Native: 0.062 seconds
        Reflection: 0.207 seconds
        Reflection: 0.203 seconds

        But hardly worth the effort, as it defeats our initial purpose of reflecting over our struct's members.

        5 Use Cases

        So, where does this leave us? What are good use cases for this? Obviously, if you're working a lot of NSManagedObject's, this will considerably slow down your code base. Also if you only have one or two structs, it is easier, more performant, and less magical if you simply write a serialization technique yourself with the domain knowledge of your individual struct.

        Rather, the reflection technique showcased here can be used if you have many, complicated structs, and you'd like to store some of those sometimes.

        Examples would be:

        • Setting Favorites
        • Storing Bookmarks
        • Staring Items
        • Keeping the last selection
        • Storing the ast open item across restarts
        • Temporary storage of items during specific processes.

        Apart from that, of course, you can also use reflection for other use cases:

        • Iterate over tuples
        • Analyze classes
        • Runtime analysis of object conformance
        • Generated detailed logging / debugging information automatically (i.e. for externally generated objects)

        6 Discussion

        The Reflection API exists primarily as a tool for the Playgrounds. Objects conforming to the reflection API can easily be displayed in a hierarchical way in the playgrounds sidebar. Thus, the performance is not optimal. Nevertheless, this has still interesting use cases outside of playgrounds as we explained in the Use Cases chapter.

        7 More Information

        The source documentation of the Reflection API is very detailed. I'd encourage everyone to have a look at that as well.

        Also, there's a much more exhaustive implementation of the techniques showcased here in the CoreValue project on GitHub which allows you to easily encode and decode from / to Structs to CoreData.

        Footnotes:

        1

        In particular, Any is an empty protocol and everything implicitly conforms to this protocol

        2

        Or rather, an empty optional

        3

        I've shortened the documentation a bit

        If you read this far, you should follow me (@terhechte)
        on Twitter


          Sat, 17 Oct 2015 #

          Advanced & Practical Enum usage in Swift

          This post is also available in 🇨🇳Chinese Thanks to SwiftGG

          When and how to use enums in Swift? This is a detailed practical overview of all the possibilities enums can offer you.

          Similarly to the switch statement, enum's in Swift may at first glance look like a slightly improved variant of the well known C enum statement. I.e. a type that allows you to define that something is "one of something more general". However, upon close introspection, the particular design decisions behind Swift's enums allow it to be used in a much wider range of practical scenarios than plain C enums. In particular, they're great tools to clearly manifest the intentions of your code.

          In this post, we'll first look at the syntax and possibilities of using enum, and will then use them in a variety of (hopefully) practical, real world scenarios to give a better idea of how and when to use them. We'll also look a bit at how enums are being used in the Swift Standard library.

          Before we dive in, here's a definition of what enums can be. We'll revisit this definition later on:

          "Enums declare types with finite sets of possible states and accompanying values. With nesting, methods, associated values, and pattern matching, however, enums can define any hierarchically organized data."

          1 Diving In

          A short overview of how to define and use enums.

          1.1 Defining Basic Enums

          We're working on a game, and the player can move in four directions. So our player movement is restricted. Obviously, we can use an enum for that.

          enum Movement {
          case Left
          case Right
          case Top
          case Bottom
          }
          

          You can then use various pattern matching constructs to retrieve the value of a Movement, or act upon a specific case:

          let aMovement = Movement.Left
          
          switch aMovement {
          case .Left: print("left")
          default: ()
          }
          
          if case .Left = aMovement { print("left") }
          
          if aMovement == .Left { print("left") }
          

          Note that you don't have to specify the actual name of the enum (i.e. case Movement.Left: print("Left") in this case. The type checker figures that out automatically. This is extremely helpful for some of those convoluted UIKit or AppKit enums.

          1.2 Enum Values

          Of course, you may want to have a value assigned to each enum case. This is useful if the enum itself indeed relates to something which can be expressed in a different type. C allows you to assign numbers to enum cases. Swift gives you much more flexibility here:

          // Mapping to Integer
          enum Movement: Int {
              case Left = 0
              case Right = 1
              case Top = 2
              case Bottom = 3
          }
          
          // You can also map to strings
          enum House: String {
              case Baratheon = "Ours is the Fury"
              case Greyjoy = "We Do Not Sow"
              case Martell = "Unbowed, Unbent, Unbroken"
              case Stark = "Winter is Coming"
              case Tully = "Family, Duty, Honor"
              case Tyrell = "Growing Strong"
          }
          
          // Or to floating point (also note the fancy unicode in enum cases)
          enum Constants: Double {
              case π = 3.14159
              case e = 2.71828
              case φ = 1.61803398874
              case λ = 1.30357
          }
          

          For String and Int types, you can even omit the values and the Swift compiler will do the right thing:

          // Mercury = 1, Venus = 2, ... Neptune = 8
          enum Planet: Int {
              case Mercury = 1, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune
          }
          
          // North = "North", ... West = "West"
          enum CompassPoint: String {
              case North, South, East, West
          }
          

          Swift supports the following types for the value of an enum:

          • Integer
          • Floating Point
          • String
          • Boolean

          So you won't be able1 to use, say, a CGPoint as the value of your enum.

          If you want to access the values, you can do so with the rawValue property:

          let bestHouse = House.Stark
          print(bestHouse.rawValue)
          // prints "Winter is coming"
          

          However, there may also be a situation where you want to construct an enum case from an existing raw value. In that case, there's a special initializer for enums:

          enum Movement: Int {
              case Left = 0
              case Right = 1
              case Top = 2
              case Bottom = 3
          }
          // creates a movement.Right case, as the raw value for that is 1
          let rightMovement = Movement(rawValue: 1)
          

          If you use the rawValue initializer, keep in mind that it is a failable initializer, i.e. you get back an Optional, as the value you're using may not map to any case at all, say if you were to write Movement(rawValue: 42).

          This is a very useful feature in case you want to encode low level C binary representations into something much more readable. As an example, have a look as this encoding of the VNode Flags for the BSD kqeue library:

          enum VNodeFlags : UInt32 {
              case Delete = 0x00000001
              case Write = 0x00000002
              case Extended = 0x00000004
              case Attrib = 0x00000008
              case Link = 0x00000010
              case Rename = 0x00000020
              case Revoke = 0x00000040
              case None = 0x00000080
          }
          

          This allows you to use the much nicer looking Delete or Write cases, and later on hand the raw value into the C function only when it is really needed.

          1.3 Nesting Enums

          If you have specific sub type requirements, you can also logically nest enums in an enum. This allows you to contain specific information on your enum case within the actual enum. Imagine a character in an RPG. Each character can have a weapon, all characters have access to the same set of weapons. All other instances in the game do not have access to those weapons (they're trolls, they just have clubs).

          enum Character {
            enum Weapon {
              case Bow
              case Sword
              case Lance
              case Dagger
            }
            enum Helmet {
              case Wooden
              case Iron
              case Diamond
            }
            case Thief
            case Warrior
            case Knight
          }
          

          Now you have a hierachical system to describe the various items that your character has access to.

          let character = Character.Thief
          let weapon = Character.Weapon.Bow
          let helmet = Character.Helmet.Iron
          

          1.4 Containing Enums

          In a similar vein, you can also embed enums in structs or classes. Continuing with our previous example:

          struct Character {
             enum CharacterType {
              case Thief
              case Warrior
              case Knight
            }
            enum Weapon {
              case Bow
              case Sword
              case Lance
              case Dagger
            }
            let type: CharacterType
            let weapon: Weapon
          }
          
          let warrior = Character(type: .Warrior, weapon: .Sword)
          

          This, again, helps in keeping related information together.

          1.5 Associated Values

          Associated values are a fantastic way of attaching additional information to an enum case. Say you're writing a trading engine, and there're two different possible trade types. Buy and Sell. Each of them would be for a specific stock and amount:

          1.5.1 Simple Example

          enum Trade {
              case Buy
              case Sell
          }
          func trade(tradeType: Trade, stock: String, amount: Int) {}
          

          However, the stock and amount clearly belong to the trade in question, having them as separate parameters feels unclean. You could embed it into a struct, but associated values allow for a much cleaner solution:

          enum Trade {
              case Buy(stock: String, amount: Int)
              case Sell(stock: String, amount: Int)
          }
          func trade(type: Trade) {}
          

          1.5.2 Pattern Matching

          If you want to access this information, again, pattern matching comes to the rescue:

          let trade = Trade.Buy(stock: "APPL", amount: 500)
          if case let Trade.Buy(stock, amount) = trade {
              print("buy \(amount) of \(stock)")
          }
          

          1.5.3 Labels

          Associated values do not require labels:

          enum Trade {
             case Buy(String, Int)
             case Sell(String, Int)
          }
          

          If you add them, though, you'll have to type them out when creating your enum cases.

          1.5.4 Tuples as Arguments

          What's more, the Swift internal associated information is just a Tuple, so you can do things like this:

          let tp = (stock: "TSLA", amount: 100)
          let trade = Trade.Sell(tp)
          
          if case let Trade.Sell(stock, amount) = trade {
              print("buy \(amount) of \(stock)")
          }
          // Prints: "buy 100 of TSLA"
          

          This syntax allows you to take Tuples as a simple data structure and later on automatically elevate them into a higher type like a enum case. Imagine an app where a user can configure a Desktop that he wants to order:

          typealias Config = (RAM: Int, CPU: String, GPU: String)
          
          // Each of these takes a config and returns an updated config
          func selectRAM(_ config: Config) -> Config {return (RAM: 32, CPU: config.CPU, GPU: config.GPU)}
          func selectCPU(_ config: Config) -> Config {return (RAM: config.RAM, CPU: "3.2GHZ", GPU: config.GPU)}
          func selectGPU(_ config: Config) -> Config {return (RAM: config.RAM, CPU: config.CPU, GPU: "NVidia")}
          
          enum Desktop {
             case Cube(Config)
             case Tower(Config)
             case Rack(Config)
          }
          
          let aTower = Desktop.Tower(selectGPU(selectCPU(selectRAM((0, "", "") as Config))))
          

          Each step of the configuration updates a tuple which is handed in to the enum at the end. This works even better if we take a hint from functional programming apply 2:

          infix operator <^> { associativity left }
          
          func <^>(a: Config, f: (Config) -> Config) -> Config { 
              return f(a)
          }
          

          Finally, we can thread through the different configuration steps. This is particularly helpful if you have many of those steps.

          let config = (0, "", "") <^> selectRAM  <^> selectCPU <^> selectGPU
          let aCube = Desktop.Cube(config)
          

          1.5.5 Use Case Examples

          Associated Values can be used in a variety of ways. As code can tell more than a thousand words, what follows is a list of short examples in no particular order.

          // Cases can have different values
          enum UserAction {
            case OpenURL(url: NSURL)
            case SwitchProcess(processId: UInt32)
            case Restart(time: NSDate?, intoCommandLine: Bool)
          }
          
          // Or imagine you're implementing a powerful text editor that allows you to have
          // multiple selections, like Sublime Text here:
          // https://www.youtube.com/watch?v=i2SVJa2EGIw
          enum Selection {
            case None
            case Single(Range<Int>)
            case Multiple([Range<Int>])
          }
          
          // Or mapping different types of identifier codes
          enum Barcode {
              case UPCA(numberSystem: Int, manufacturer: Int, product: Int, check: Int)
              case QRCode(productCode: String)
          }
          
          // Or, imagine you're wrapping a C library, like the Kqeue BSD/Darwin notification
          // system: https://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2
          enum KqueueEvent {
              case UserEvent(identifier: UInt, fflags: [UInt32], data: Int)
              case ReadFD(fd: UInt, data: Int)
              case WriteFD(fd: UInt, data: Int)
              case VnodeFD(fd: UInt, fflags: [UInt32], data: Int)
              case ErrorEvent(code: UInt, message: String)
          }
          
          // Finally, all user-wearable items in an RPG could be mapped with one
          // enum, that encodes for each item the additional armor and weight
          // Now, adding a new material like 'Diamond' is just one line of code and we'll have the option to add several new Diamond-Crafted wearables.
          enum Wearable {
              enum Weight: Int {
          	case Light = 1
          	case Mid = 4
          	case Heavy = 10
              }
              enum Armor: Int {
          	case Light = 2
          	case Strong = 8
          	case Heavy = 20
              }
              case Helmet(weight: Weight, armor: Armor)
              case Breastplate(weight: Weight, armor: Armor)
              case Shield(weight: Weight, armor: Armor)
          }
          let woodenHelmet = Wearable.Helmet(weight: .Light, armor: .Light)
          

          1.6 Methods and Properties

          You can also define methods on an enum like so:

          enum Wearable {
              enum Weight: Int {
          	case Light = 1
              }
              enum Armor: Int {
          	case Light = 2
              }
              case Helmet(weight: Weight, armor: Armor)
              func attributes() -> (weight: Int, armor: Int) {
                 switch self {
          	 case .Helmet(let w, let a): return (weight: w.rawValue * 2, armor: a.rawValue * 4)
                 }
              }
          }
          let woodenHelmetProps = Wearable.Helmet(weight: .Light, armor: .Light).attributes()
          print (woodenHelmetProps)
          // prints "(2, 8)"
          

          Methods on enums exist for every enum case. So if you want to have specific code for specific cases, you need a branch or a switch to determine the correct code path.

          enum Device { 
              case iPad, iPhone, AppleTV, AppleWatch 
              func introduced() -> String {
                 switch self {
          	 case .AppleTV: return "\(self) was introduced 2006"
          	 case .iPhone: return "\(self) was introduced 2007"
          	 case .iPad: return "\(self) was introduced 2010"
          	 case .AppleWatch: return "\(self) was introduced 2014"
                 }
              }
          }
          print (Device.iPhone.introduced())
          // prints: "iPhone was introduced 2007"
          

          1.6.1 Properties

          Even though you can't add actual stored properties to an enum, you can still create computed properties. Their contents, of course, can be based on the enum value or enum associated value.

          enum Device {
            case iPad, iPhone
            var year: Int {
              switch self {
          	case .iPhone: return 2007
          	case .iPad: return 2010
               }
            }
          }
          

          1.6.2 Static Methods

          You can also have static methods on enums, i.e. in order to create an enum from a non-value type. In this example we want to get the proper Apple Device for the wrong name that's sometimes used by people.

          enum Device { 
              case AppleWatch 
              static func fromSlang(term: String) -> Device? {
                if term == "iWatch" {
          	  return .AppleWatch
                }
                return nil
              }
          }
          print (Device.fromSlang(term:"iWatch")!)
          

          1.6.3 Mutating Methods

          Methods can be declared mutating. They're then allowed to change the case of the underlying self parameter 3:

          enum TriStateSwitch {
              case Off, Low, High
              mutating func next() {
          	switch self {
          	case .Off:
          	    self = .Low
          	case .Low:
          	    self = .High
          	case High:
          	    self = .Off
          	}
              }
          }
          var ovenLight = TriStateSwitch.Low
          ovenLight.next()
          // ovenLight is now equal to .High
          ovenLight.next()
          // ovenLight is now equal to .Off
          

          1.7 To Recap

          We've finished our overview of the basic use cases of Swift's enum syntax. Before we head into the advanced usage, lets have another look at the explanation we gave at the beginning and see if it became clearer now.

          Enums declare types with finite sets of possible states and accompanying values. With nesting, methods, associated values, and pattern matching, however, enums can define any hierarchically organized data.

          The definition is a lot clearer now. Indeed, if we add associated values and nesting, an enum case is like a closed, simplified struct. The advantage over structs being the ability to encode categorization and hierachy:

          // Struct Example
          struct Point { let x: Int, y: Int }
          struct Rect { let x: Int, y: Int, width: Int, height: Int }
          
          // Enum Example
          enum GeometricEntity {
             case Point(x: Int, y: Int)
             case Rect(x: Int, y: Int, width: Int, height: Int)
          }
          

          The addition of methods and static methods allow us to attach functionality to an enum without having to resort to free functions 4

          // C-Like example
          enum Trade {
             case Buy
             case Sell
          }
          func order(trade: Trade)
          
          // Swift Enum example
          enum Trade {
             case Buy
             case Sell
             func order() {}
          }
          

          2 Advanced Enum Usage

          2.1 Protocols

          I already mentioned the similarity between the structs and enums. In addition to the ability to add methods, Swift also allows you to use Protocols and Protocol Extensions with enums.

          Swift protocols define an interface or type that other structures can conform to. In this case our enum can conform to it. For a start, let's take a protocol from the Swift standard library.

          CustomStringConvertible is a type with a customized textual representation suitable for printing purposes:

          protocol CustomStringConvertible {
            var description: String { get }
          }
          

          It has only one requirement, namely a getter for a string. We can implement this on an enum quite easily:

          enum Trade: CustomStringConvertible {
             case Buy, Sell
             var description: String {
                 switch self {
          	   case .Buy: return "We're buying something"
          	   case .Sell: return "We're selling something"
                 }
             }
          }
          
          let action = Trade.Buy.description
          print("this action is \(action)")
          // prints: this action is We're buying something
          

          Some protocol implementations may need internal state handling to cope with the requirements. Imagine a protocol that manages a bank account:

          protocol AccountCompatible {
            var remainingFunds: Int { get }
            mutating func addFunds(amount: Int) throws
            mutating func removeFunds(amount: Int) throws
          }
          

          You could easily fulfill this protocol with a struct, but in the context of your application, an enum is the more sensible approach. However, you can't add properties like var remainingFunds: Int to an enum, so how would you model that? The answer is actually easy, you can use associated values for this:

          enum Account {
            case Empty
            case Funds(remaining: Int)
          
            enum Error: Swift.Error {
              case Overdraft(amount: Int)
            }
          
            var remainingFunds: Int {
              switch self {
              case .Empty: return 0
              case .Funds(let remaining): return remaining
              }
            }
          }
          

          To keep things clean, we can then define the required protocol functions in a protocol extension on the enum:

          extension Account: AccountCompatible {
          
            mutating func addFunds(amount: Int) throws {
              var newAmount = amount
              if case let .Funds(remaining) = self {
                newAmount += remaining
              }
              if newAmount < 0 {
                throw Error.Overdraft(amount: -newAmount)
              } else if newAmount == 0 {
                self = .Empty
              } else {
                self = .Funds(remaining: newAmount)
              }
            }
          
            mutating func removeFunds(amount: Int) throws {
              try self.addFunds(amount * -1)
            }
          
          }
          
          var account = Account.Funds(remaining: 20)
          print("add: ", try? account.addFunds(amount:10))
          print ("remove 1: ", try? account.removeFunds(amount:15))
          print ("remove 2: ", try? account.removeFunds(amount:55))
          // prints:
          // : add:  Optional(())
          // : remove 1:  Optional(())
          // : remove 2:  nil
          

          As you can see, we implemented all the protocol requirements by storing our values within our enum cases. A very nifty side effect of this is, that now you can test for an empty account with a simple pattern match all over your code base. You don't have to see whether the remainingFunds are zero.

          We're also nesting an ErrorType compatible enum in the Account enum so that we can use Swift 2.0's new error handling. This is explained in more detail in the Practical Use Cases section.

          2.2 Extensions

          As we just saw, enums can also be extended. The most apparent use case for this is keeping enum cases and methods separate, so that a reader of your code can easily digest the enum and after that move on to the methods:

          enum Entities {
              case Soldier(x: Int, y: Int)
              case Tank(x: Int, y: Int)
              case Player(x: Int, y: Int)
          }
          

          Now, we can extend this enum with methods:

          extension Entities {
             mutating func move(dist: CGVector) {}
             mutating func attack() {}
          }
          

          You can also write extensions to add support for a specific protocol:

          extension Entities: CustomStringConvertible {
            var description: String {
              switch self {
                 case let .Soldier(x, y): return "\(x), \(y)"
                 case let .Tank(x, y): return "\(x), \(y)"
                 case let .Player(x, y): return "\(x), \(y)"
              }
            }
          }
          

          2.3 Generic Enums

          Enums can also be defined over generic parameters. You'd use them to adapt the associated values of an enum. The simplest example comes straight from the Swift standard library, namely the Optional type. You probably mostly use it with optional chaining (?), if let, guard let, or switch, but syntactically you can also use Optionals like so:

          let aValue = Optional<Int>.some(5)
          let noValue = Optional<Int>.none
          if noValue == Optional.none { print("No value") }
          

          This is the direct usage of an Optional without any of the syntactic sugar that Swift adds in order to make your life a tremendous amount easier. If you look at the code above, you can probably guess that internally the Optional is defined as follows 5:

          // Simplified implementation of Swift's Optional
          enum MyOptional<T> {
            case Some(T)
            case None
          }
          

          What's special here is, that the enum's associated values take the type of the generic parameter T, so that optionals can be built for any kind you wish to return.

          Enums can have multiple generic parameters. Take the well-known Either type which is not part of Swift's standard library but implemented in many open source libraries as well as prevalent in other functional programming languages like Haskell or F#. The idea is that instead of just returning a value or no value (née Optional) you'd return either the successful value or something else (probably an error value).

          // The well-known either type is, of course, an enum that allows you to return either
          // value one (say, a successful value) or value two (say an error) from a function
          enum Either<T1, T2> {
            case Left(T1)
            case Right(T2)
          }
          

          Finally, all the type constraints that work on classes and structs in Swift also work on enums.

          // Totally nonsensical example. A bag that is either full (has an array with contents)
          // or empty.
          enum Bag<T: Sequence> where T.Iterator.Element==Equatable {
              case Empty
              case Full(contents: T)
          }
          

          2.4 Recursive / Indirect Types

          Indirect types are a new addition that came with Swift 2.0. They allow you to define enums where the associated value of a case is the very same enum again. As an example, consider that you want to define a file system representations with files and folders containing files. If File and Folder were enum cases, then the Folder case would need to have an array of File cases as it's associated value. Since this is a recursive operation, the compiler has to make special preparations for it. Quoting from the Swift documentation:

          Enums and cases can be marked indirect, which causes the associated value for the enum to be stored indirectly, allowing for recursive data structures to be defined.

          So to implement our FileNode enum, we'd have to write it like this:

          enum FileNode {
            case File(name: String)
            indirect case Folder(name: String, files: [FileNode])
          }
          

          The indirect keyword tells the compiler to handle this enum case indirectly. You can also add the keyword for the whole enum. As an example imagine mapping a binary tree:

          indirect enum Tree<Element: Comparable> {
              case Empty
              case Node(Tree<Element>,Element,Tree<Element>)
          }
          

          This is a very powerful feature that allows you to map complex relationships in a very clean way with an enum.

          2.5 Using Custom Data Types as Enum Values

          If we neglect associated values, then the value of an enum can only be an Integer, Floating Point, String, or Boolean. If you need to support something else, you can do so by implementing the StringLiteralConvertible protocol which allows the type in question to be serialized to and from String.

          As an example, imagine you'd like to store the different screen sizes of iOS devices in an enum:

          enum Devices: CGSize {
             case iPhone3GS = CGSize(width: 320, height: 480)
             case iPhone5 = CGSize(width: 320, height: 568)
             case iPhone6 = CGSize(width: 375, height: 667)
             case iPhone6Plus = CGSize(width: 414, height: 736)
          }
          

          However, this doesn't compile. CGSize is not a literal and can't be used as an enum value. Instead, what you need to do is add a type extension for the StringLiteralConvertible protocol. The protocol requires us to implement three initializers each of them is being called with a String, and we have to convert this string into our receiver type (CGSize)

          extension CGSize: ExpressibleByStringLiteral {
              public init(stringLiteral value: String) {
          	let size = CGSizeFromString(value)
          	self.init(width: size.width, height: size.height)
              }
          
              public init(extendedGraphemeClusterLiteral value: String) {
          	let size = CGSizeFromString(value)
          	self.init(width: size.width, height: size.height)
              }
          
              public init(unicodeScalarLiteral value: String) {
          	let size = CGSizeFromString(value)
          	self.init(width: size.width, height: size.height)
              }
          }
          

          Now, we can write our enum, with one downside though: The initial values have to be written as a String, since that's what the enum will use (remember, we complied with StringLiteralConvertible, so that the String can be converted to our CGSize type.

          enum Devices: CGSize {
             case iPhone3GS = "{320, 480}"
             case iPhone5 = "{320, 568}"
             case iPhone6 = "{375, 667}"
             case iPhone6Plus = "{414, 736}"
          }
          

          This, finally, allows us to use our CGSize enum. Keep in mind that in order to get the actual CGSize value, we have to access the rawvalue of the enum.

          let a = Devices.iPhone5
          let b = a.rawValue
          print("the phone size string is \(a), width is \(b.width), height is \(b.height)")
          // prints : the phone size string is iPhone5, width is 320.0, height is 568.0
          

          The String serialization requirement makes it a bit difficult to use any kind of type, but for some specific use cases, this can work well (such as NSColor / UIColor). However, you can also use this with your custom types obviously.

          2.6 Comparing Enums with associated values

          Enums, by nature, are easily comparable by equality. A simple enum T { case a, b} implementation supports the proper equality tests T.a == T.a, T.b != T.a.

          If you add associated values though, Swift cannot correctly infer the equality of two enums, and you have to implement the == operator yourself. This is simple though:

          enum Trade {
              case Buy(stock: String, amount: Int)
              case Sell(stock: String, amount: Int)
          }
          func ==(lhs: Trade, rhs: Trade) -> Bool {
             switch (lhs, rhs) {
               case let (.Buy(stock1, amount1), .Buy(stock2, amount2))
          	   where stock1 == stock2 && amount1 == amount2:
          	   return true
               case let (.Sell(stock1, amount1), .Sell(stock2, amount2))
          	   where stock1 == stock2 && amount1 == amount2:
          	   return true
               default: return false
             }
          }
          

          As you can see, we're comparing the two possible enum cases via a switch, and only if the cases match (i.e. .Buy & .Buy) will we compare the actual associated values.

          2.7 Custom Initializers

          In the context of static methods on enums, we already mentioned that they can be used as a way to conveniently create an enum from different data. The example we had was for returning the proper Apple device for the wrong worded version that the press sometimes uses:

          enum Device { 
              case AppleWatch 
              static func fromSlang(term: String) -> Device? {
                if term == "iWatch" {
          	  return .AppleWatch
                }
                return nil
              }
          }
          

          Instead of using a static method for this, we can also use a custom initializer. The main difference compared to a Swift struct or class is that within an enum initializer, you need to set the implicit self property to the correct case.

          enum Device { 
              case AppleWatch 
              init?(term: String) {
                if term == "iWatch" {
          	  self = .AppleWatch
                } else {
          	  return nil
                }
              }
          }
          

          In the above example, we used a failable initializer. However, normal initializers work just as well:

          enum NumberCategory {
             case Small
             case Medium
             case Big
             case Huge
             init(number n: Int) {
          	if n < 10000 { self = .Small }
          	else if n < 1000000 { self = .Medium }
          	else if n < 100000000 { self = .Big }
          	else { self = .Huge }
             }
          }
          let aNumber = NumberCategory(number: 100)
          print(aNumber)
          // prints: "Small"
          

          2.8 Iterating over Enum Cases

          One particularly often asked question with regards to enums is how to iterate over all cases. Sadly, enums do not conform to the SequenceType protocol, so there is no official way to do this. Depending on the type of enum that you have, it might be easier or more difficult to implement a way of iterating over all cases. There's a very good overview in this StackOverflow thread. Also, there's so much variation in the replies that it wouldn't to listing only some of the examples here. On the other hand, listing all the examples would be too much.

          2.9 Objective-C support

          Integer-based enums such as enum Bit: Int { case Zero = 0; case One = 1} can be bridged to Objective-c via the @objc flag. However once you venture away from integers (say String) or start using associated values you can't use enums from within Objective-C.

          There's a hidden protocol called _ObjectiveCBridgeable which apparently allows defining the proper methods so that Swift can convert things back and forth from Objective-C, but I suppose there's a reason why it is hidden. Nevertheless, theoretically it should allow you to add support for bridging an enum (including associated values) to Objective-C.

          You don't have to do it that way though. Add two methods to your enum, define a type replacement on the @objc side, and you can move enums back and forth just fine, without having to conform to private protocols:

          enum Trade {
              case Buy(stock: String, amount: Int)
              case Sell(stock: String, amount: Int)
          }
          
          // This type could also exist in Objective-C code.
          @objc class OTrade: NSObject {
              var type: Int
              var stock: String
              var amount: Int
              init(type: Int, stock: String, amount: Int) {
          	self.type = type
          	self.stock = stock
          	self.amount = amount
              }
          }
          
          extension Trade  {
          
              func toObjc() -> OTrade {
          	switch self {
          	case let .Buy(stock, amount):
          	    return OTrade(type: 0, stock: stock, amount: amount)
          	case let .Sell(stock, amount):
          	    return OTrade(type: 1, stock: stock, amount: amount)
          	}
              }
          
              static func fromObjc(source: OTrade) -> Trade? {
          	switch (source.type) {
          	case 0: return Trade.Buy(stock: source.stock, amount: source.amount)
          	case 1: return Trade.Sell(stock: source.stock, amount: source.amount)
          	default: return nil
          	}
              }
          }
          

          This still has the downside that you need to mirror your enum via an NSObject based type on the Objective-C side (or you could just go and use an NSDictionary), but if you ever end up in a situation where you need to access an enum with associated values from Objective-C, this is a way to do it.

          2.10 Enum Internals

          Erica Sadun wrote a great blog post explaining the internals of enums when you look at the bits and bytes behind the glossy syntax. This is something you should never do in production code, but still interesting to know. We'll only mention one of her findings here, but go and read her original article for more.

          Enums are typically one byte long. […] If you want to get very very silly, you can build an enumeration with hundreds of cases, in which case the enum takes up 2 or more bytes depending on the minimum bit count needed.

          3 Enums in the Swift Standard Library

          Before we go on and explore various use cases for enums in your projects, it might be tempting to see some of the enums being used in the Swift standard library, so let's have a look.

          Bit The Bit enum can have two possible values, One, and Zero. It is used as the Index type for CollectionOfOne<T>.

          FloatingPointClassification This enum defines the set of possible IEEE 754 "classes", like NegativeInfinity, PositiveZero, or SignalingNaN.

          Mirror.AncestorRepresentation, and Mirror.DisplayStyle These two are used in the context of the Swift Reflection API.

          Optional Not much to say here

          Process The Process enum contains the command line arguments of the current process (Process.argc, Process.arguments). This is a particularly interesting enum as it used to be a struct in Swift 1.0.

          4 Practical Use Cases

          We've already seen a couple of useful enums in the previous feature descriptions. Examples would be Optional, Either, FileNode, or the binary tree. However, there're many more scenarios where using an enum wins over a struct or class. Usually, if your problem domain can be divided into a finite set of distinctive categories, an enum may be the right choice. Even only two cases are a perfectly valid scenario for an enum, as the Optional and Either types show.

          Here, then, are some more examples of practical enum usage to fuel your creativity.

          Advanced & Practical Enum usage in Swift4.1 Error Handling

          One of the prime examples of Enum usage in Swift is, of course, the new error handling in Swift 2.0. Your throwing function can throw anything which conforms to the empty ErrorType protocol. As the Swift documentation succinctly observes:

          Swift enumerations are particularly well suited to modeling a group of related error conditions, with associated values allowing for additional information about the nature of an error to be communicated.

          As an example, have a look at the popular JSON Decoding library Argo. When their JSON Decoding fails, it can fail due to two primary reasons.

          1. The JSON Data lacks a key which the end model requires (say your model has a property username and somehow the JSON lacks that)
          2. There's a type mismatch. Say instead of a String the username property in the JSON contains an NSNull 6.

          In addition to that, Argo also includes a custom error for anything not fitting in these two categories above. Their ErrorType enum looks like this:

          enum DecodeError: Error {
            case TypeMismatch(expected: String, actual: String)
            case MissingKey(String)
            case Custom(String)
          }
          

          All cases have associated values that contain additional information about the error in question.

          A more general ErrorType for complete HTTP / REST API handling could look like this:

          enum APIError : Error {
              // Can't connect to the server (maybe offline?)
              case ConnectionError(error: NSError)
              // The server responded with a non 200 status code
              case ServerError(statusCode: Int, error: NSError)
              // We got no data (0 bytes) back from the server
              case NoDataError
              // The server response can't be converted from JSON to a Dictionary
              case JSONSerializationError(error: Error)
              // The Argo decoding Failed
              case JSONMappingError(converstionError: DecodeError)
          }
          

          This ErrorType implements the complete REST Stack up to the point where your app would get the completely decoded native struct or class object.

          If you look closely, you'll see that within the JSONMappingError, we're wrapping the Argo DecodeError into our APIError type as we're still using Argo for the actual JSON decoding.

          More information on ErrorType and more enum examples in this context can be found in the official documentation here.

          4.2 Observer Pattern

          There're various ways of modelling observation in Swift. If you include @objc compatibility, you can use NSNotificationCenter or KVO. Even if not, the didSet syntax makes it easy to implement simple observation. Enums can be used here in order to make the type of change that happens to the observed object clearer. Imagine collection observation. If we think about it, we only have a couple of possible cases: One or more items are inserted, one or more items are deleted, one or more items are updated. This sounds like a job for an enum:

          enum Change {
               case Insertion(items: [Item])
               case Deletion(items: [Item])
               case Update(items: [Item])
          }
          

          Then, the observing object can receive the concrete information of what happened in a very clean way. This could easily be extended by adding oldValue and newValue, too.

          4.3 Status Codes

          If you're working with an outside system which uses status codes (or error codes) to convey information, like HTTP Status Codes, enums are obviously a great way to encode the information. 7

          enum HttpError: String {
            case Code400 = "Bad Request"
            case Code401 = "Unauthorized"
            case Code402 = "Payment Required"
            case Code403 = "Forbidden"
            case Code404 = "Not Found"
          }
          

          4.4 Map Result Types

          Enums are also frequently used to map the result of JSON parsing into the Swift type system. Here's a short example of this:

          enum JSON {
              case JSONString(Swift.String)
              case JSONNumber(Double)
              case JSONObject([String : JSONValue])
              case JSONArray([JSONValue])
              case JSONBool(Bool)
              case JSONNull
          }
          

          Similarly, if you're parsing something else, you may use the very same structure to convert your parsing results into Swift types. This also makes perfect sense to only do it during the parsing / processing step and then taking the JSON enum representation and converting it into one of your application's internal class or struct types.

          4.5 UIKit Identifiers

          Enums can be used to map reuse identifiers or storyboard identifiers from stringly typed information to something the type checker can understand. Imagine a UITableView with different prototype cells:

          enum CellType: String {
              case ButtonValueCell = "ButtonValueCell"
              case UnitEditCell = "UnitEditCell"
              case LabelCell = "LabelCell"
              case ResultLabelCell = "ResultLabelCell"
          }
          

          4.6 Units

          Units and unit conversion are another nice use case for enums. You can map the units and their respective values and then add methods to do automatic conversions. Here's an oversimplified example.

          enum Liquid: Float {
            case ml = 1.0
            case l = 1000.0
            func convert(amount: Float, to: Liquid) -> Float {
                if self.rawValue < to.rawValue {
          	 return (self.rawValue / to.rawValue) * amount
                } else {
          	 return (self.rawValue * to.rawValue) * amount
                }
            }
          }
          // Convert liters to milliliters
          print (Liquid.l.convert(amount: 5, to: Liquid.ml))
          

          Another example of this would be Currency conversion. Also, mathematical symbols (such as degrees vs radians) can benefit from this.

          4.7 Games

          Enums are a great use case for games, where many entities on screen belong to a specific family of items (enemies, obstacles, textures, …). In comparison to native iOS or Mac apps, games oftentimes are a tabula rasa. Meaning you invent a new world with new relationships and new kinds of objects, whereas on iOS or OSX you're using a well-defined world of UIButtons, UITableViews, UITableViewCells or NSStackView.

          What's more, since Enums can conform to protocols, you can utilize protocol extensions and protocol based programming to add functionality to the various enums that you defined for your game. Here's a short example that tries to display such a hierarchy:

          enum FlyingBeast { case Dragon, Hippogriff, Gargoyle }
          enum Horde { case Ork, Troll }
          enum Player { case Mage, Warrior, Barbarian }
          enum NPC { case Vendor, Blacksmith }
          enum Element { case Tree, Fence, Stone }
          
          protocol Hurtable {}
          protocol Killable {}
          protocol Flying {}
          protocol Attacking {}
          protocol Obstacle {}
          
          extension FlyingBeast: Hurtable, Killable, Flying, Attacking {}
          extension Horde: Hurtable, Killable, Attacking {}
          extension Player: Hurtable, Obstacle {}
          extension NPC: Hurtable {}
          extension Element: Obstacle {}
          

          4.8 Battling stringly typed code

          In bigger Xcode projects, you're quickly accumulating lots of resources which are accessed by string. We've already mentioned reuse identifiers and storyboard identifiers above, but there's also: Images, Segues, Nibs, Fonts, and other resources. Oftentimes, those resources can be grouped into several distinct sets. If that's the case, a String typed enum is a good way of having the compiler check this for you.

          enum DetailViewImages: String {
            case Background = "bg1.png"
            case Sidebar = "sbg.png"
            case ActionButton1 = "btn1_1.png"
            case ActionButton2 = "btn2_1.png"
          }
          

          For iOS users, there's also R.swift which auto generates structs for most of those use cases. Sometimes you may need more control though (or you may be on a Mac 8)

          4.9 API Endpoints

          Rest APIs are a great use case for enums. They're naturally grouped, they're limited to a finite set of APIs, and they may have additional query or named parameters which can be modelled through associated values.

          Take, for example, a look at a simplified version of the Instagram API

          enum Instagram {
            enum Media {
              case Popular
              case Shortcode(id: String)
              case Search(lat: Float, min_timestamp: Int, lng: Float, max_timestamp: Int, distance: Int)
            }
            enum Users {
              case User(id: String)
              case Feed
              case Recent(id: String)
            }
          }
          

          Ash Furrow's Moya library is based around this idea of using enums to map rest endpoints.

          4.10 Linked Lists

          Airspeed Velocity has a great writeup on how to implement a Linked List with an enum. Most of the code in his post goes far beyond enums and touches a lot of interesting topics 9, but the basis of his linked list looks kinda like this (I simplified it a bit):

          enum List {
              case End
              indirect case Node(Int, next: List)
          }
          

          Each Node case points to the next case, and by using an enum instead of something else, you don't have to use an optional for the next value to signify the termination of the list.

          Airspeed Velocity also wrote a great post about the implementation of a red black tree with indirect Swift enums, so while you're already reading his blog, you may just as well also read this one.

          Advanced & Practical Enum usage in Swift4.11 Settings Dictionaries

          This is a very, very smart solution that Erica Sadun came up with. Basically whenever you'd use a dictionary of attribute keys as a way to configure an item, you'd instead use a Set of enums with associated values. That way, the type checker can confirm that your configuration values are of the correct type.

          For more details, and proper examples, check out her original blog post.

          5 Limitations

          We're ending this post, again, with a list of things that don't work yet with enums.

          5.1 Retrieving Associated Values

          David Owens makes the case that the current way of associated value retrieval is unwieldy. I encourage you to follow the link and read the post, but here's the gist: In order to retrieve the associated values from an enum, you have to use pattern matching. However, associated values are effectively tuples which were attached to the enum case. Tuples, on the other hand, can be deconstructed in a much simpler way simply by using .keyword or .0. i.e:

          // Enums
          enum Ex { case Mode(ab: Int, cd: Int) }
          if case Ex.Mode(let ab, let cd) = Ex.Mode(ab: 4, cd: 5) {
              print(ab)
          }
          // vs tuples:
          let tp = (ab: 4, cd: 5)
          print(tp.ab)
          

          If you also feel that this is how we should be able to deconstruct enums, there's a rdar for you: rdar://22704262

          5.2 Equatable

          Enums with associated values do not conform to the equatable protocol. That's a pity because it makes a lot of things much more cumbersome and verbose than they need to be. The underlying reason is probably that associated values are just tuples internally and tuples do not conform to equatable. However, for a limited subset of cases, namely those where all associated value / tuple types conform to equatable, I think the default case should be that the compiler automatically also generates the equatable extension.

          // Int and String are Equatable, so case Ex should also be equatable.
          enum Ex { case Mode(ab: Int, cd: String) }
          
          // Swift could auto-generate this func
          func == (lhs: Ex.Mode, rhs: Ex.Mode) -> Bool {
              switch (lhs, rhs) {
                 case (.Mode(let a, let b), .Mode(let c, let d)):
          	   return a == c && b == d
                 default:
          	   return false
              }
          }
          

          5.3 Tuples

          The biggest issue is, again, Tuple support. I love tuples, they make many things easier, but they're currently under-documented and cannot be used in many scenarios. In terms of enums, you can't have tuples as the enum value:

          enum Devices: (intro: Int, name: String) {
            case iPhone = (intro: 2007, name: "iPhone")
            case AppleTV = (intro: 2006, name: "Apple TV")
            case AppleWatch = (intro: 2014, name: "Apple Watch")
          }
          

          This may not look like the best example, but once you start using enums, you'll often end up in situations where you'd like to be able to do something like the above.

          5.4 Enumerating Enum Cases

          We've already discussed this above. There's currently no good way to get a collection of all the cases in an enum so you can iterate over them.

          5.5 Default Associated Values

          Another thing which you may run into is that associated values are always types but you can't set a default value for those types. Imagine such an example:

          enum Characters {
            case Mage(health: Int = 70, magic: Int = 100, strength: Int = 30)
            case Warrior(health: Int = 100, magic: Int = 0, strength: Int = 100)
            case Neophyte(health: Int = 50, magic: Int = 20, strength: Int = 80)
          }
          

          You could still create new cases with different values, but the default settings for your character would be mapped.

          6 Changes

          10/26/2015

          • Added additional limitation examples (Equatable & Retrieving associated values)
          • Added Erica Sadun's Set with Associated Enums example

          10/22/2015

          • Incorporated PR #6 from @mabidakun.
          • Added internal links
          • Split up the account example into two easier to digest snippets.

          10/21/2015

          Footnotes:

          1

          Except by jumping through some hoops, see below

          2

          This is a simplified implementation for demo purposes. In reality you'd write this with optionals and a reverse argument order. Have a look at popular functional programming libraries like Swiftz or Dollar

          3

          This example stems straight from Apple's Swift documentation

          4

          Which make it oftentimes very difficult to discover them

          5

          This is a simplified version, of course. Swift adds a lot of sugar for you

          6

          If you ever used JSON in an app, you may well have run into this issue once

          7

          Btw. You can't use only numbers as enum case names, so case 400 does not work

          8

          Although Mac support for R.swift seems to be forthcoming

          9

          Translated: Go there, read it

          If you read this far, you should follow me (@terhechte)
          on Twitter