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, 29 Mar 2016 #

Three tips for concise Swift using the Guard statement

This will be a shorter post compared to some of my previous ones, but I wanted to share three useful guard tips for structuring your functions in such a way that you end up with code that is more concise and also easier to understand1. This is not a post about general coding styles or coding guidelines, but more about how guard can help you simplify your code.

Some of this might also have appeared in one of my larger posts on enums or pattern matching, but for different use cases. Let's dive right in:

1 Binding and Condition Combination

1.1 Nesting

The first example concerns the use of pattern matching in order to let2 bind variables into the current scope. One thing I really like about this syntax (compared to, say if let) is that it keeps a golden code path, guarding*3 you from the all-too common *skyscraper of death. Compare:

// Lots of nonsensical code to show how nested code structures look confusing
if let a = a() {
  let x = b(a)
  x.fn()
  if let u = x.nxt() {
    let ux = u.brm()
    if let uxt = ux.nxt() {
       perform(uxt)
    }
  }
}

with:

guard let a = a() else { return }
let x = b(a)
x.fn()
guard let u = x.nxt() else { return }
let ux = u.brm()
guard let uxt = ux.nxt() else { return }

perform(uxt)

Now these are awful examples of how not to structure an internal API, but they exist more to drive a point home. Guard is great because it binds the result into the current scope instead of the nested scope. In larger functions, this makes all the difference between having huge, difficult-to-grasp deeply-nested functions and clean versions which look almost like lists of commands.

1.2 Pattern Binding

The above works even better, if your input is an enum. Consider how we're handling the following usecase:

protocol NotificationListener {
  func handleNotification(notification: Notification)
}
enum Notification {
  case UserLoggedIn(user: String, date: NSDate, domain: String)
  case FileUploaded(file: String, location: String, size: Int, user: String)
}

struct FileUploadHandler: NotificationListener {
  /**
    Implement the notification handling to move uploaded files to temporary folder
  */
  func handleNotification(notification: Notification) {
    guard case .FileUploaded(let file, let location, _, let user) = notification
    else { return }

    if user == self.currentUser {
       self.moveFile(file, atLocation: location)
    }
  }
}

The binding in the guard case line achieves two things for us:

  1. It makes sure handleNotifications only works for FileUploaded notifications, and not for UserLoggedIn notifications.
  2. It binds all the associated values of the enum into the current scope, making it easy for us to use the data.

1.3 Where Clauses

However, with the power of guard, we can even simplify the example. Lo and behold:

struct FileUploadHandler: NotificationListener {
  /**
    Implement the notification handling to move uploaded files to temporary folder
  */
  func handleNotification(notification: Notification) {
    guard case .FileUploaded(let file, let location, _, let user) = notification
    where user == self.currentUser
    else { return }
    self.moveFile(file, atLocation: location)
  }
}

Now, the code is even shorter as the where clause of the guard expression does the correct matching for us.

You can have multiple where clauses in your guard statement:

import Foundation

func confirmPath(pathObject: AnyObject) -> Bool {
  guard let url = pathObject as? NSURL,
  let components = url.pathComponents
    where components.count > 0,
  let first = components.dropFirst().first
    where first == "Applications",
  let last = components.last
    where last == "MyApp.app"
  else { return false }
  print("valid folder", last)
  return true
}
print(confirmPath(NSURL(fileURLWithPath: "/Applications/MyApp.app")))
// : valid folder MyApp.app
// : true

As you can see here, we're combining multiple let bindings with related where clauses which makes it easy to handle all the preconditions in one bigger guard statement instead of having to break it up into multiple singular statements.

1.4 Nested Enums

The above even works for nested enums. This may sound like a far-fetched example, but I do actually have a project where I'm using a nested enum. In this example, we have a list of different items in the sidebar of an Instagram client. Those can be headlines, seperators, or folders:

enum SidebarEntry {
  case Headline(String)
  case Item(String)
  case Seperator
}

A sidebar could be defined by an array like this:

[.Headline("Global"),
 .Item("Dashboard"),
 .Item("Popular"),
 .Seperator,
 .Headline("Me"),
 .Item("Pictures"),
 .Seperator,
 .Headline("Folders"),
 .Item("Best Pics 2013"),
 .Item("Wedding")
]

Here, each Item would have to have a different action: I.e. clicking "Dashboard" should do something different compared to clicking "Pictures", or the "Wedding" folder. The solution I chose was to have another, nested, enum within the Item enum:

enum Action {
  case .Popular
  case .Dashboard
  case .Pictures
  case .Folder(name: String)
}

enum SidebarEntry {
  case Headline(String)
  case Item(name: String, action: Action)
  case Seperator
}

[.Headline("Global"),
 .Item(name: "Dashboard", action: .Dashboard),
 .Item(name: "Popular", action: .Popular),
 .Item(name: "Wedding", action: .Folder("fo-wedding")]

Now, if we want publish a folder (to the cloud) we'd like to really make sure that we were called with a folder and not a headline or a Popular item:

func publishFolder(entry: SidebarEntry)  {
  guard case .Item(_, .Folder(let name)) = entry 
  else { return }
  Folders.sharedFolders().byName(name).publish()
}

This is a great way to model complex hirachies but still be able to match even intricate, nested types.

2 One-Line Guard Return

This is a short one. When you end up in the else case, you may want to perform an action before you return:

guard let a = b() else {
   print("wrong action")
   return
}
// or
guard let a = b() else {
   self.completion(items: nil, error: "Could not")
   return
}

As long as your command returns void, you can actually combine these into one:

guard let a = b() else {return print("wrong action")}
// or
guard let a = b() else {
   return self.completion(items: nil, error: "Could not")
}

I find this much easier on the eyes and better to read. However, it may reduce readability in a complex project when another developer runs into this and wonders what kind of type is being returned here.

Alternatively, you can also use the semicolon in these cases4:

guard let a = b() else {
  print("argh"); return
}

3 try? in guards

Finally, in cases where you'd need to perform a throwable function, and you don't care about the error result, you can still happily use guard just by utilizing the try? syntax, which converts the result of your throwing call into an optional, depending on whether it worked or not:

guard let item = item,
   result = try? item.perform()
else { return print("Could not perform") }

The neat thing about this is that it allows us to combine various Swift mechanics into one safe call to make sure that our code can safely proceed.

4 Wrapping Up

Everything combined into one long example. This also shows how you can combine case and let in one guard.

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

That's it. For more detailed information, I recommend reading my much larger articles on pattern matching and enums.

Footnotes:

1

In my humble opinion, that is

2

Or var bind

3

Hint Hint

4

After leaving Objective-C behind, you'll probably have to search your keyboard to find the key for it again ;)

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


    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 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, also, may not have a name for their entries.

          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