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.

Thu, 28 Apr 2016 #

SwiftWatch

And now for something slightly different. I'm not sure how others perceive this, but I find it very difficult to keep on track of all the exciting developments in the Swift community. There're so many fascinating GitHub projects, valuable conference talks, educational blog posts, insightful Twitter discussions and fantastic newsletters that it is hard to keep yourself updated on recent developments. To make matters worse, the scope of Swift is also expanding from iOS/watchOS/tvOS/macOS development to Linux server development and now even Android development.

There're several great Swift & iOS newsletters that remedy this situation in part, but they only appear once a week and usually showcase a limited, curated selection of what happened during the week. There's also the reddit Swift community, but the myriad of subreddits (like iOS, Mac, programming, etc), again, requires the visiting of multiple different locations in order to get an overview 1.

After feeling constantly overwhelmed and underinformed, I decided to try to do something about this. I'm an avid reader of Hacker News, and, to me, it feels as if what's missing is a place like Hacker News 2 but solely for everything Swift. A place to share interesting Swift tidbits and (maybe) discuss them.

So without further ado, let me introduce SwiftWatch:





SwiftWatch tries to be this place. I'd not call it a community or a social network. Rather, it is a place to share interesting Swift news. You have to register with a Twitter or Github account, in order to (ever so slightly) decrease the likelihood of spam. Commenting is possible, but I don't envision this site to be a source of great discussions. Instead, I'd be more than happy if people start using it to post interesting Swift developments.

If you have any feedback regarding Swiftwatch, feel free to contact me on Twitter.

As you can see, @renelindhorst 3 and I have already been feeding the page with a couple of links which we deemed interesting enough to post them.

The site is based on Monocle, an open source link sharing platform. I'd have rather developed something in Swift but that'd have consumed too much time. If SwiftWatch survives (i.e. if it gains decent traction) then I'd seriously consider rewriting the guts in Swift3 + one of those nice Web Frameworks (like Perfect).

Thanks for reading!

PS: In case you're wondering "SwiftWatch" is named after the peculiar habbit of birdwatching, "a form of wildlife observation in which the observation of birds is a recreational activity". I found this a particularly good fit as the core objective of this site is quite similar.

Footnotes:

1

Alternatively, one can sign up on reddit and meticulously manage one's subreddit subscriptions, but not everybody does that

2

or LamerNews or Designer News or Product Hunt

3

Thanks Rene!

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


    Sat, 23 Apr 2016 #

    Raw value initializers for enums with associated types

    Enums are a beautiful way of structuring information in Swift. Sometimes you find yourself initializing enums from raw values, maybe because the values were intermittendly stored somewhere else, say in the NSUserDefaults:

    enum Device: String {
      case phone, tablet, watch
    }
    let aDevice = Device(rawValue: "phone")
    print(aDevice)
    
    Prints Optional(main.Device.phone)
    

    1 The Problem

    As soon as you're using associated values in your enums, this doesn't work anymore:

    enum Example {
       case Factory(workers: Int)
       case House(street: String)
    }
    

    Swift can't create an instance of Example because the two cases, Factory and House have different associated types (the workers integer and the street string. Each invocation of Example requires different parameters, so this can't be generalized.

    However, that's not the case when your associated types all match up:

    enum Device {
        case phone(name: String, screenSize: CGSize)
        case watch(name: String, screenSize: CGSize)
        case tablet(name: String, screenSize: CGSize)
    }
    

    In thise case, all the associated types are the same. There're a myriad of other ways to model this, but I found the device enum to be a concise example for what I'm about to explain. Even though every Device invocation is the same now, you still can't just call it with some sort of raw value and expect the correct type. Instead, what you have to do is perform a match in order to create the correct instance:

    import Foundation
    
    enum Device {
        case phone(name: String, screenSize: CGSize)
        case watch(name: String, screenSize: CGSize)
        case tablet(name: String, screenSize: CGSize)
    
        static func fromDefaults(rawValue: String, name: String, screenSize: CGSize) -> Device? {
    	switch rawValue {
    	case "phone": return Device.phone(name: name, screenSize: screenSize)
    	case "watch": return Device.watch(name: name, screenSize: screenSize)
    	case "tablet": return Device.tablet(name: name, screenSize: screenSize)
    	default: return nil
    	}
        }
    }
    let b = Device.fromDefaults("phone", name: "iPhone SE", screenSize: CGSize(width: 640, height: 1136))
    print(b)
    
    prints Optional(main.Device.phone("iPhone SE", (640.0, 1136.0)))
    

    This looks ok, but it is already a bit of repetitive code. Once you develop more than just three enum cases / two associated types, this will quickly get out of hand.

    enum Vehicle {
      case .car(wheels: Int, capacity: Int, weight: Int, length: Int, height: Int, width: Int, color: Int, name: Int, producer: Int, creation: NSDate, amountOfProducedUnits: Int)
      case .ship(wheels: Int, capacity: Int, weight: Int, length: Int, height: Int, width: Int, color: Int, name: Int, producer: Int, creation: NSDate, amountOfProducedUnits: Int)
      case .yacht(wheels: Int, capacity: Int, weight: Int, length: Int, height: Int, width: Int, color: Int, name: Int, producer: Int, creation: NSDate, amountOfProducedUnits: Int)
      case .truck(wheels: Int, capacity: Int, weight: Int, length: Int, height: Int, width: Int, color: Int, name: Int, producer: Int, creation: NSDate, amountOfProducedUnits: Int)
      case .motorbike(wheels: Int, capacity: Int, weight: Int, length: Int, height: Int, width: Int, color: Int, name: Int, producer: Int, creation: NSDate, amountOfProducedUnits: Int)
      case .helicopter(wheels: Int, capacity: Int, weight: Int, length: Int, height: Int, width: Int, color: Int, name: Int, producer: Int, creation: NSDate, amountOfProducedUnits: Int)
      case .train(wheels: Int, capacity: Int, weight: Int, length: Int, height: Int, width: Int, color: Int, name: Int, producer: Int, creation: NSDate, amountOfProducedUnits: Int)
      ...
    }
    

    I think you get my point.

    2 The Solution

    So.. how do we solve this? Interestingly, there's a quirky similarity between the initializer of an associated type and a closure. Take this code:

    enum Example {
      case test(x: Int)
    }
    let exampleClosure = Example.test
    

    What is the type of exampleClosure here? The type is (Int) -> Example. That's right, calling an associated value enum case without any parameters will yield a closure that, when called with the correct types, will return an instance of said type.

    This means that, the following is valid, working Swift:

    enum Fruit {
      case apple(amount: Int)
      case orange(amount: Int)
    }
    let appleMaker = Fruit.apple
    let firstApple = appleMaker(amount: 10)
    let secondApple = appleMaker(amount: 12)
    print(firstApple, secondApple)
    
    apple(10) apple(12)
    

    So, how would that help us simplify the gross code duplication problem above? Have a look:

    import Foundation
    
    enum Device {
        case phone(name: String, screenSize: CGSize)
        case watch(name: String, screenSize: CGSize)
        case tablet(name: String, screenSize: CGSize)
    
        private static var initializers: [String: (name: String, screenSize: CGSize) -> Device] = {
    	return ["phone": Device.phone, "watch": Device.watch, "tablet": Device.tablet]
        }()
    
        static func fromDefaults(rawValue: String, name: String, screenSize: CGSize) -> Device? {
    	return Device.initializers[rawValue]?(name: name, screenSize: screenSize)
        }
    }
    
    let iPhone = Device.fromDefaults("phone", name: "iPhone SE", screenSize: CGSize(width: 640, height: 1134))
    print(iPhone)
    
    Optional(main.Device.phone("iPhone SE", (640.0, 1134.0)))
    

    So, let's try to figure out what happened here. We have a new property initializers on our Device. It's a Dictionary of type [String: (name: String, screenSize: CGSize) -> Device]. I.e. something that maps from a String key to a closure with the same type as our Device cases. The dictionary contains the initializers of each of our distinct cases, simply by using the same trick as above, just handing in the closure: phone:Device.phone

    The fromDefaults function, then, only has to know the key of the device we'd like to create, and it can call the appropriate closure. This leads to a much shorter implementation, especially for bigger enums (like our Vehicle example above). As you can see, creating a Device instance is then as simple as:

    Device.initializers["phone"]?(name: "iPhone 5", screenSize: CGSize(width: 640, height: 1134)))
    

    Just as with raw values, in case there is no enum case phone we'd just get an empty optional back.

    This solution isn't perfect of course. You still have to have the initializers dictionary, however it will be much less repetitve than having to match over all cases manually.

    Finally, I suppose it goes without saying that the code above ignores an important best practice to be concise and to be able to concentrate on the task at hand; Nevertheless: having stringified code like Device.initializers["phone"] is not the best way to write this. Instead, those keys should be properly defined somewhere else.

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


      Thu, 14 Apr 2016 #

      Force optionals in multi-unwrapped "guard let" or "if let"

      I really love unwrapping optionals in a multi- guard or let statement with additional where clauses added. See my previous post on this here. However, sometimes I run into a situation where I have one function call (or a array subscript) in between my others that does not return an optional:

      // Imagine this function does something complicated
      func someArray() -> [Int]? {
          return [1, 2, 3, 4, 5, 6]
      }
      
      func example() {
          guard let array = someArray(),
      	numberThree = array[2]
      	where numberThree == 3
      	else { return }
          print(numberThree)
      }
      

      This doesn't work. The compiler will explain to you that it expects an optional:

      "Initializer for conditional binding must have Optional type, not 'Int'"

      So, what you oftentimes end up with, instead, is something like this:

      func example() {
          guard let array = someArray() else { return }
          let numberThree = array[2]
          guard numberThree == 3 else { return }
          print(numberThree)
      }
      

      Not only is this awful to look at, you also have to write the failure block twice. That's ok for a simple example as this one { return }, but when you have to perform a bit more work in there you'll have to repeat code blocks; and that's bad 1.

      So what's the solution here? Well, since the guard or let requires an optional, we can just as well create one and unpack it again:

      func example() {
          guard let array = someArray(),
      	numberThree = Optional.Some(array[2])
      	where numberThree == 3
      	else { return }
          print(numberThree)
      }
      

      As you may remember, Swift's optionals are internally more or less enums with a .Some and a .None case. So what we're doing here is creating a new .Some case only to unwrap it again in the very same line: The array[2] expression will be wrapped with Optional.Some and then unwrapped again into numberThree.

      There is a wee bit of overhead here, but on the other hand it does allow us to keep the guard or let unwrappings much cleaner.

      This obviously doesn't just work with array subscripts like array[3] but also with any non-optional function, i.e.:

      guard let aString = optionalString(),
          elements = Optional.Some(aString.characters.split("/")),
          last = elements.last,
          count = Optional.Some(last.characters.count),
          where count == 5 else { fatalError("Wrong Path") }
      print("We have \(count) items in \(last)")
      

      Footnotes:

      1

      Or you start refactoring this into seperate closures or functions, but that's an awful lot of work for just one guard statement

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


        Mon, 4 Apr 2016 #

        Using Git Hooks to prevent commiting test code

        Today I'd like to share a quick setup which I'm using in most of my local Git repositories nowadays to prevent me from accidentally commiting certain exploratory lines of code which fall neither in between the debug / release flags nor unit tests.

        Here's a quick example: Imagine you're writing an app that shows the current trending links out of Hacker News, Reddit, and Product Hunt combined. For each source, you're setting up an importer:

        let importers = [
          importerHackerNews()
          importerReddit(),
          importerProductHunt()
        ]
        

        However, while you're working on a new feature, Hacker News is down. This isn't a problem in itself, but each time you start up the app you're greeted with a popup reminding you that your app can't currently import from Hacker News.

        So, in order to be productive again, you quickly comment out the HackerNews importer, making a mental note to uncomment it before you commit todays changes:

        let importers = [
          // REMEMBER: Only temporary
          // importerHackerNews()
          importerReddit(),
          importerProductHunt()
        ]
        

        Later on, when you collect all the change hunks of the new feature into your Git staging area, you're obviously performing due dilligence and carefully examining each change to make sure that there're no unwanted lines.

        However, sometimes something slips through, and that's when your Hacker News importer suddenly doesn't work anymore. There're of course multiple ways to prevent this:

        • In a perfect world you'd have a unit test set up which catches this on your CI server (or even before that on your local system).
        • You can add FIXME lines and generate warnings or errors during building (if you're working in a compiled language)
        • You can write notes or todos on your system

        My problem with all the above approaches is that they're a bit indirect, oftentimes requiring the setup or housekeeping of a secondary system just to make sure nothing slips through.

        1 Using Git Hooks as a solution

        I'd rather play it safe here. Whether or not I have unit tests for small temporary changes like these, whatever happens, under no circumstances should I be allowed to commit this. My solution is the addition of a commented tag which will be picked up by a Git Hook in order to tell Git that it is not safe to commit the project in its current state. You can chose any tag you want, I decided to use the tag #BABOON#. The only requirement here is that the chance is very unlikely that you'd write this tag somewhere else in your codebase as part of the actual source code.

        When that tag has been added to the staging area like so:

        let importers = [
          // #BABOON#(comment out again)
          // importerHackerNews()
          importerReddit(),
          importerProductHunt()
        ]
        

        And I'm trying to commit this, Git will fail with an exception. It does that because I've added the following hook to my Git repository:

        #!/bin/sh
        if git rev-parse --verify HEAD >/dev/null 2>&1
        then
        	against=HEAD
        else
        	# Initial commit: diff against an empty tree object
        	against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
        fi
        
        # The special marker tag to mark things which we still need to change
        marker="#BABOON#"
        
        # Redirect output to stderr.
        exec 1>&2
        
        if test $(git diff --cached -z $against | grep $marker | wc -c) != 0 
        then
            cat <<\EOF
            Error: Still has invalid debug markers in code:
        EOF
            echo `git diff --cached -z $against -G $marker`
            exit 1
        fi
        

        This file has to be stored within your Git repository at the following place:

        .git/hooks/pre-commit
        

        What that script does is whenever you're trying to commit, it will run a grep search against all currently staged changes (git diff --cached -z $against | grep $marker | wc -c) and will test if there're more than zero results. If that's the case, the script will exit with a 1 which signifies to Git that it should not continue running.

        As outlined above, there're several other solutions for the above problem, but I like having this one in my Git repo as the first line of defense.

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


          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