Matthew Palmer

  1. Rocket: Slack-style Emoji Everywhere on your Mac

    Last week I released Rocket, a Mac app that gives you Slack-style emoji autocomplete everywhere you type on your Mac.

    rocket

    The launch of Rocket easily had the best reception for any app I’ve made—quite a dream launch. Some highlights:

    • Front page of Product Hunt with around 200 upvotes
    • ~2,200 downloads, ~1,300 installs
    • My tweet about it went a bit crazy, with like 130 retweets and a few hundred favs
    • Featured on iMore

    A couple of lowlights, now that I think about it:

    • the app auto-update integration I added doesn’t seem to be working in the 1.0… I think lots of people will never get to use the newer versions
    • the app wasn’t quite done when I decided to ship (I wasn’t expecting this response!)—the licensing stuff, the custom gifs and emojis, and a few bugs weren’t in there. This meant that I didn’t make any revenue off the launch (that’s okay though, the rush of the launch was good enough).

    A thought I had considering that this is my first launch that anyone could consider successful: even with being featured and all the tweets and everyone being so positive, say I had the licensing stuff in there, and say it was $6. Now let’s just say that 5% of the 1,300 people who installed the app got the upgrade (I reckon that’s a bit high, but we’ll go with it). That’s 65 people × $7 upgrade = $455. Even with a dream launch—how the hell does anyone make money off software? Maybe for my dream launch I didn’t have my dreams high enough?

    Anyway, I couldn’t be happier. These have a been very exciting days.

  2. How to Record Podcast Audio from Your iPhone or Mac for $150

    For a new podcast project, I’ve done a lot of microphone, preamp, and digital recorder research. This guide and review shows you how to record podcasts and audio from your iPhone or Mac with one set of gear, and with the best bang for buck sound quality.

    These were my requirements:

    • be able to record on the go (iPhone, Zoom, etc.)
    • be able to record from my Mac (or PC)
    • be able to record an XLR microphone to both of these devices
    • keep costs as low as possible
    • be able to upgrade different parts of the setup later (e.g. I might want a better mic, to switch to a Zoom, etc.)

    I was able to get this done for around $150 US (depending on Amazon prices at the time you order).

    Summary

    I’ll review each bit of podcasting equipment individually below, but here’s where I ended up after a tonne of research:

    A quick note: this probably isn’t the cheapest overall way to record your podcast, but this is the best way that I’ve found to be able to record from both iPhone and Mac without having two sets of gear, and where each piece of equipment is upgradeable later on. You might be better served by an iPhone-specific microphone (which I nearly ended up buying) and a USB mic for your computer. If you have a setup that other people might like, let me know on Twitter and I’ll add them to this post.



    I make Transducer, a Mac app for posting your podcast to Libsyn or SoundCloud. If this guide helps you, please consider giving it a download—there’s a 20-day free trial, and it’s only $5 after that.



    Audio sample using the iRig Pro and Pyle PDMIC58

    Here is an episode of my podcast that we recorded via Skype using the iRig Pro and Pyle PDMIC58. We were pretty happy with the sound quality considering that each host has very little room treatment. We found that this audio quality was comparable to (if not better than) another episode we recorded using a Rode podcaster microphone.

    iRig Pro review for podcasting

    The iRig Pro is a really flexible audio interface that lets you connect an XLR microphone to your iPhone or computer for a pretty reasonable cost ($135 on Amazon at time of writing).

    Digital recorders, like the Zoom H4n, are the iRig’s main competitor, but those recorders don’t let you record to your phone (and only some of them can be used with computers). They’re also much, much more expensive than the iRig.

    Pros

    • The iRig can be used with both iPhone and Mac. I don’t know many other devices that can do this!
    • Works with any XLR microphone (though I wouldn’t put a mic that required a tonne of gain on it)
    • The iRig itself is really compact and light—much lighter than I anticipated
    • Recording is really simple for both iPhone and Mac. It’s more or less plug and play, with a little bit of software that I’ll go into in its own section
    • Audio recordings have good sound quality as long as you don’t turn the iRig’s gain above 3 o’clock (any higher you start to get a lot of noise). Thankfully, I found 3 o’clock a pretty comfortable position for spoken word audio recording. You’ll need to remove noise and increase the levels after the recording, but using Audition I found that this didn’t introduce any extra noise to the recording.

    Cons

    • The iRig uses these totally bizarre first party cables that I’ve never seen anywhere else… I’m terrified of losing them!
    • You can’t use headphones that have an inline mic to monitor sound (I’m guessing the iPhone picks the headphones’ mic over the one to the Lightning port). There’s also a little delay when monitoring your voice with headphones.
    • It can be a little ungainly to hold, walk, and talk at the same time with all the cords going everywhere

    Overall, the iRig solves a problem that not many other devices are solving, and does it very well. I was pretty skeptical going into the purchase (no one seems to be using iRigs for podcasting), but I was pleasantly surprised. It’s not perfect, but it’s a good solution that fits my needs.

    Pyle Pro PDMIC58 microphone review for podcasting

    The Pyle-Pro PDMIC58 is a dynamic microphone that provides unfathomably good value for money, running at around $15 on Amazon. This is a purchase that comes via Marco Arment’s microphone mega-review. If you don’t have one, you’ll need a pop filter—I got this Shure one for like $5 that does the job. Another thing to note is that this microphone doesn’t come with an XLR cable. If you’re thinking of recording while walking around, I’d recommend a short XLR cable or getting some velcro zip ties to coil up the cord while on the move.

    Pros

    • Cheap cheap cheap
    • Good sound quality

    Cons

    • Doesn’t come with an XLR cable
    • Build quality is average

    Overall, the way I’d describe the Pyle is that the build quality is what you’d expect for $15, but the sound is worth 4x that. This is a great value purchase, and it can be easily swapped out for a better XLR microphone later on. I’d even get one just as a backup microphone they’re such good value.

    The best iPhone app for recording a podcast from your iPhone

    I tried as many of the available iPhone audio recording apps as I could get my hands on. Most of them are bad to decent, but the best I found was Apple’s Voice Memos, which comes with the phone. For recording on the Mac with the iRig and Pyle, you can just use QuickTime—the iRig can be used like any other USB audio input, which is a great feature.

    Pros

    • Really easy to use and to start recording quickly
    • Simple to export many recordings at once by connecting to iTunes (some of the other apps had really terrible export options)
    • Works “through” the lock screen—i.e. you can start recording, lock your phone, and recording will keep going (and the phone even gives you live levels and recording progress on the lock screen). This was an awesome surprise when I discovered it!
    • Allows pausing and resuming a recording
    • Comes free with the phone

    Cons

    • You have to give stuff a name when saving, where the default is “Voice Recording #x”. Not a big deal, but a little annoying when you’re trying to record a few clips quickly

    Here are the other apps that I tried:

    • Apple’s Music Memos. This is a new app that does a reasonably good job, but missing some of the awesome features of Voice Memos. One thing this app does really well is boosting voice, so if you ever forget your microphone, I’d consider recording with this app as a last resort.
    • Voice Recorder
    • Awesome Voice Recorder
    • Voice Record Pro 7
    • Voice Record Pro
    • iRig Recorder. This is the option that the makers of the iRig offer. It doesn’t do anything really special.

    Conclusion

    With the iRig Pro for $135 on Amazon and the Pyle-Pro PDMIC58 for $15 on Amazon I was able to create a mobile and desktop podcast recording setup.

  3. Transducer 1.0

    I’ve been working on a Mac app that makes posting podcasts to Libsyn and SoundCloud way easier. This is the first Mac app I’ve ever made, and I’ve just released the first version. Download Transducer for OS X for free and let me know what you think.

    This started as a cobbled together Shell script, and has grown pretty organically from there. First, I just wanted a way to automate posting a new podcast episode to a Jekyll blog. Then, I wanted to get the file’s metadata and have that automatically filled in for the RSS feed. Then, I wanted to set the ID3 metadata, and to not have to type the same stuff out week after week.

    The 1.0 gives me exactly the workflow I wanted:

    1. Choose the audio file you want to post
    2. Choose the podcast you’re posting it for
    3. Fill in some metadata (title, description, etc.)
    4. Upload to Libsyn (or SoundCloud!)
    5. Run a custom script to create a Jekyll post that’ll eventually end up in the podcast’s RSS feed

    The design’s definitely not as polished as I’d like, and there are still some rough edges, but I’m hoping it’ll make posting a podcast a little bit easier.

  4. Protocol Oriented Programming in the Real World

    This weekend, I rewrote most of Locksmith, my library for using the iOS keychain, to be protocol-oriented. This was a fascinating process, and one that isn’t yet finished.

    Why?

    The primary reason I tried out a protocol-oriented approach was to manage complexity in a type-safe way.

    The big problem with the iOS keychain is the sheer complexity of it. There are five types of keychain items: generic passwords, internet passwords, certificates, keys, and identities. For each of these, you have four operations: create, read, update, and delete. That’s 20 operations, all with different attributes that need to be set and things that can go wrong.

    The way I thought about it, we have customization on two axes: types of items, and operations on items.

    To accomplish this, the actual Cocoa implementation uses a bunch of string constants and difficult to remember key/value combinations. This works, but it’s not user-friendly. You don’t know what’s gone wrong and why, and you never know the expected type of something without diving for the docs.

    With Locksmith, I wanted to have the same power as the Cocoa implementation, but in a way that made use of the type system and felt Swift-native.

    What do you get out of protocols?

    A couple of awesome things emerge when you focus on protocols

    • you can add functionality in new dimensions to existing types
    • you can easily adapt a rapidly growing API
    • you can decouple certain parts of your API for flexibility and testing

    Dimensions

    Say we have a Twitter account, which is a struct. And let’s say that we want to be able to save the username and password for that struct to the keychain.

    struct TwitterAccount {
      let username: String
      let password: String
    }

    In the past, we might’ve added a method to this struct to save it to the keychain.

    struct TwitterAccount {
      let username: String
      let password: String
    
      func saveToKeychain() throws {
        try Locksmith.saveData(["username": username, "password": password], forUserAccount: "username", inService: "Twitter")
      }
    }

    This is okay, but there’s a lot we don’t know about a given TwitterAccount from its declaration. Plus, we’re a bit limited by what that library provides to us.

    But with Locksmith’s new protocol oriented design, we get some nice functionality for free.

    struct TwitterAccount: CreateableSecureStorable, GenericPasswordSecureStorable {
      let username: String
      let password: String
    
      // Required for `GenericPasswordSecureStorable`
      let service = "Twitter"
      var account: String { return username }
    
      // Required for `CreateableSecureStorable`
      var data: [String: AnyObject] {
        return ["password": password]
      }
    }

    And with the method we get from Createable, we can save our item

    let t = TwitterAccount(username: "_matthewpalmer", password: "my_password")
    try t.saveInKeychain()

    Oh, and guess what… if we conform to Readable and Deleteable on that struct (which have no additional requirements), then we can use readFromKeychain() and deleteFromKeychain without adding any other code!

    struct TwitterAccount: GenericPasswordSecureStorable,
                           CreateableSecureStorable,
                           ReadableSecureStorable,
                           DeleteableSecureStorable {
      // ...
    }
    
    let t = TwitterAccount(username: "_matthewpalmer", password: "my_password")
    try t.saveInKeychain()
    // For free!
    let result = t.readFromKeychain()
    try t.deleteFromKeychain()

    That’s really awesome. It almost feels like using mixins or stylesheets in CSS.

    Consider this as well: in the first instance, we conformed to two protocols. One for Createable, which works for anything that can provide data, and one for GenericPassword, which works for anything that belongs to a service and has an account.

    Two axes of customization.

    Imagine a 4×5 chessboard, where for each square on the bottom you have one of our actions: create, read, update, and delete. On the vertical, you’ve got a square for each type of item: generic password, internet password, certificate, key, and identity.

    20 different permutations of closely-related stuff is tough to model. But with protocols and protocol extensions, it becomes so much easier. With protocol extensions, protocols add functionality in new dimensions.

    That’s cool, but it’s probably not clear just how cool that really is. Let me tell you one more thing.

    We’ve seen that generic passwords have a service and an account. Those are required. What I didn’t show you was that generic passwords can also have creationDate, modificationDate, description, comment, creator, label, type, isInvisible, and isNegative. (And some of them don’t have the type you’d expect!)

    Let’s extend our TwitterAccount to use some of these.

    struct TwitterAccount: CreateableSecureStorable, GenericPasswordSecureStorable {
      let username: String
      let password: String
    
      // Required for `GenericPasswordSecureStorable`
      let service = "Twitter"
      var account: String { return username }
    
      // Required for `CreateableSecureStorable`
      var data: [String: AnyObject] {
        return ["password": password]
      }
    
      // Optional for `GenericPasswordSecureStorable`
      let creationDate: NSDate? = NSDate()
      let description: String? = "A Twitter account"
      let type: UInt? = 13
      let comment: String? = "Woah, this is complicated."
    }

    Too easy! We just added the properties onto our type.

    But wait… if we wanted to use the old static func approach, how would we do that?

    You might create methods that have optional or default arguments, but that explodes with complexity really quickly.

    Or you could pass around a dictionary and check against some agreed-upon keys, but then you don’t get the type system working for you. You’d never know what was required and what was optional, and it’s impossible to know for sure at compile time.

    Protocol oriented programming is the best approach I can think of to deal with this complexity and configurability.

    When I was first implementing this, I realised we weren’t actually returning anything useful from our readFromKeychain(). We were giving people a [String: AnyObject], which is barely a step up from where we started!

    We needed a nice type for returning data, but we also had to communicate to users that the metadata returned from a GenericPassword operation wouldn’t be the same as that returned from an InternetPassword operation—and they had to be able to know that at compile time.

    Sounds like a huge pain.

    Having protocols all the way down made it super easy to mix together the right type to return to users—we developed a ResultType, and created a couple of other protocols (GenericPasswordResultType and InternetPasswordResultType) that shared certain properties, but also provided their own unique properties.

    Plus, having this ResultType meant that we could provide actual types for the metadata we get back from the keychain—if the user saves an NSDate as metadata, they’re going to get an NSDate back. Wonderful—and almost impossible without protocols.

    Testing

    The WWDC session on protocol oriented programming mentioned testing, but it was a point that I didn’t notice at the time.

    Initially, I found that similar operations needed slightly different ways of actually performing the request (SecItemAdd vs SecItemCopyMatching, etc.). To help with code reuse, I introduced a closure on the root protocol: var performRequestClosure: (requestReference: CFDictionaryRef, inout result: AnyObject?) -> (OSStatus) { get }. Hairy.

    This started as an internal implementation detail, and became a super useful aspect of the library.

    First, it provides another point of customization, where users can change how or where certain items will be stored. If someone wants to store their type somewhere other than the iOS keychain, it’s really easy for them to do that. I use this internally in Locksmith, so that we can customize the options for a request in shared code, and then perform the request in code unique to the implementer. Very useful.

    Second, and following from the first point, we can override performRequestClosure to get access to the serialized request, and make sure we’ve added our attributes properly.

    We implement validation of the request to be performed in the closure—we take the requestReference, convert it to an NSDictionary, and check that all of the required attributes have been set.

    // Within `performRequestClosure`
    let request = requestReference as NSDictionary
    let creator = request[String(kSecAttrCreator)] as! CFNumberRef
    XCTAssertEqual(creator as UInt, expectedCreator)
    
    // ...

    That means we can easily and thoroughly test that all of the desired properties have been set, but without using mocks and relying on internal implementation!

    Wrap up

    There’s a lot to be liked about protocol oriented programming, but the big thing for me is the feeling that I still have a tonne to learn. This was my first crack at it, so if you have feedback or suggestions, feel free to contact me on Twitter.

    This was a very design-focused post. If you want to see how it’s actually implemented, check out the Locksmith Github repository.

  5. Optional Computed Properties in Swift Protocols

    You might want to declare an optional property when developing your Swift protocol, but not want to go full @objc since then you couldn’t use structs. Previously, this hasn’t been possible. Here’s one way I’ve been using to work around this.

    You have your protocol, with one required property that all conforming types must have, and one that they can optionally include

    protocol SomeProtocol {
        var required: String { get }
        var optional: String? { get }
    }

    Then, you use a protocol extension to implement that optional computed property for all conforming types

    extension SomeProtocol {
        var optional: String? { return nil }
    }

    Whenever a conforming type wants to use that optional property, if it’s set, it’ll be used, but if not, that’s fine as well!

    So now we can have structs that can choose whether they want to implement that computed property.

    struct ConformsWithoutOptional {
        let required: String
    }
    
    struct ConformsWithOptional {
        let required: String
        let optional: String?
    }

    One thing to note is that you can’t do optional: String in ConformsWithOptional and expect it to override the original optional: String? in other protocol extensions. You have to match the type exactly: optional: String?. That caught me out for a while.

    In general, it’s probably better to break up your protocols so that users can pick and choose the things they want to implement, but this is a quick and useful trick that I haven’t seen written up anywhere else.

  6. Converting Swift Playgrounds to Markdown for Blog Posts

    Swift Playgrounds are wonderful, and they have support for Markdown-style commenting. Theoretically, you could write an entire blog post in a Playground and post it online—the code could be run in-line, you’d have interactive charts, pictures, and beautiful markup. Sounds like a dream.

    I’ve created a utility to convert a playground to Markdown. It’s called Playdown, and it means you can write your posts in Playgrounds and easily convert them to blog-friendly GFM Markdown for publishing.

  7. How to Remove Icons and Text from iOS Folder Previews

    I like to keep my iPhone simple, but the nine-by-nine grid of icons that is displayed in folders isn’t great. I wanted two things: to remove the icons from the folder preview, and to remove the text label below each folder.

    Here’s where I ended up:

    my iphone homescreen with removed icons and text

    First, we’ll remove the icon preview.

    1. I’ve created a placeholder page that has the right shade of grey as the favicon. Open that page in Safari on your iPhone or iPad. Note that this might not work for all backgrounds, but if you have a regular-enough iPhone wallpaper, you should be able to make your own template site with the right favicon set. (This is my iPhone wallpaper, which works well with the placeholder favicon provided.)
    2. Hit the share button, and pan across on the bottom row.
    3. Tap ‘Add to Home Screen’, and the icon will be added to your homescreen
    4. Drag the new icon into a folder, and drag everything but the new icon to a different page. Here’s what the front page of each folder should look like.

    iphone folder with no icons

    Repeat for each folder.

    Changing the text below the folder is much easier. You do it the normal way, except copy-and-paste a symbol from a Unicode table or use emoji.

  8. UIKit Dynamics, Swift, and Falling Blocks

    This year, I entered the WWDC 2015 Scholarships competition. I didn’t win, but there were a couple of interesting parts of my app that I thought were still worth sharing.

    My design centred around rising and falling blocks that represented the different parts of my life. These blocks had mass and density and elasticity, and they responded in a lively way. And, like little blocks in a glass case, I wanted them to fall away when the device rotated.

    demo of animated uiview responding to device rotation

    I tried doing this by animating blocks from one side of the device to the other, but it just didn’t feel right. The blocks needed to be physical. I needed a physics engine: UIKit Dynamics.

    The first step to this is to get the blocks falling down the device in a realistic way. The second step is to listen for device orientation changes, and update our blocks in response to these changes.

    Skip to the end if you want to see the code in its entirety.

    We set up a new empty view, and add a green and an orange block.

    lazy var greenBlock: UIView = {
        let view = UIView(frame: CGRect(x: 50.0, y: 50.0, width: 100.0, height: 100.0))
        view.backgroundColor = UIColor.greenColor()
        return view
    }()
    
    lazy var orangeBlock: UIView = {
        let view = UIView(frame: CGRect(x: 125.0, y: 190.0, width: 50.0, height: 50.0))
        view.backgroundColor = UIColor.orangeColor()
        return view
    }()

    We also add a UIDynamicAnimator, which controls the physics for the system. We add a UIGravityBehavior, for replicating gravity, and collisions and elasticity between the items.

    // Animator for all of the components
    var itemsAnimator: UIDynamicAnimator?
    
    // Gravity for the system
    var gravityBehavior: UIGravityBehavior?
    
    // Collisions
    var boundaryCollisionBehavior: UICollisionBehavior?
    
    // Elasticity
    var elasticityBehavior: UIDynamicItemBehavior?

    Then we need to add all of these components to our master animator, and tweak the the elasticity of the blocks so they’re more bouncy.

    // Our master item animator
    itemsAnimator = UIDynamicAnimator(referenceView: view)
    
    // The gravity for our system
    gravityBehavior = UIGravityBehavior(items: blocks)
    
    // The collision between our items, and with the boundary of the containing view
    boundaryCollisionBehavior = UICollisionBehavior(items: blocks)
    boundaryCollisionBehavior?.translatesReferenceBoundsIntoBoundary = true
    
    // The elasticity for the blocks
    elasticityBehavior = UIDynamicItemBehavior(items: blocks)
    elasticityBehavior?.elasticity = 0.6
    
    // Add everything
    itemsAnimator?.addBehavior(gravityBehavior)
    itemsAnimator?.addBehavior(boundaryCollisionBehavior)
    itemsAnimator?.addBehavior(elasticityBehavior)

    At this stage, our view controller will be something like (regularGravityVector and invertedGravityVector are not needed yet, but will be useful later).

    class ViewController: UIViewController {
        // MARK: - Blocks
        
        // Our block
        lazy var greenBlock: UIView = {
            let view = UIView(frame: CGRect(x: 50.0, y: 50.0, width: 100.0, height: 100.0))
            view.backgroundColor = UIColor.greenColor()
            return view
        }()
        
        lazy var orangeBlock: UIView = {
            let view = UIView(frame: CGRect(x: 125.0, y: 190.0, width: 50.0, height: 50.0))
            view.backgroundColor = UIColor.orangeColor()
            return view
        }()
        
        
        // MARK: - Dynamics properties
        // Animator for all of the components
        var itemsAnimator: UIDynamicAnimator?
        
        // Gravity for the system
        var gravityBehavior: UIGravityBehavior?
        
        lazy var regularGravityVector: CGVector = {
            CGVector(dx: 0, dy: 1.0)
        }()
        
        lazy var invertedGravityVector: CGVector = {
            CGVector(dx: 0, dy: -1.0)
        }()
        
        // Collisions
        var boundaryCollisionBehavior: UICollisionBehavior?
        
        // Elasticity
        var elasticityBehavior: UIDynamicItemBehavior?
        
        // MARK: - View lifecycle
        override func viewDidLoad() {
            super.viewDidLoad()
            
            // Listen for orientation changes
            NSNotificationCenter.defaultCenter().addObserver(self, selector: "orientationChanged:", name: UIDeviceOrientationDidChangeNotification, object: UIDevice.currentDevice())
            
            // Add our blocks to the view
            view.addSubview(greenBlock)
            view.addSubview(orangeBlock)
            
            let blocks = [greenBlock, orangeBlock]
            
            // Our master item animator
            itemsAnimator = UIDynamicAnimator(referenceView: view)
            
            // The gravity for our system
            gravityBehavior = UIGravityBehavior(items: blocks)
            
            // The collision between our items, and with the boundary of the containing view
            boundaryCollisionBehavior = UICollisionBehavior(items: blocks)
            boundaryCollisionBehavior?.translatesReferenceBoundsIntoBoundary = true
            
            // The elasticity for the blocks
            elasticityBehavior = UIDynamicItemBehavior(items: blocks)
            elasticityBehavior?.elasticity = 0.6
            
            // Add everything
            itemsAnimator?.addBehavior(gravityBehavior)
            itemsAnimator?.addBehavior(boundaryCollisionBehavior)
            itemsAnimator?.addBehavior(elasticityBehavior)
        }
    }

    We can build and run our project, and see the cool falling-blocks effect.

    gravity simulation of falling blocks ios dynamics

    To achieve the cool effect of blocks-in-a-box, we wanted to be able to rotate the device and have the gravity flip around. This is super easy to implement, thanks to the setup we did earlier.

    We listen for the device’s orientation changes

    NSNotificationCenter.defaultCenter().addObserver(self, selector: "orientationChanged:", name: UIDeviceOrientationDidChangeNotification, object: UIDevice.currentDevice())

    and add our handling of the orientation changes

    func orientationChanged(notification: NSNotification) {
        if let device = notification.object as? UIDevice {
            switch device.orientation {
            case .Portrait:
                portraitOrientationChange()
            case .PortraitUpsideDown:
                portraitUpsideDownOrientationChange()
            default:
                return
            }
        }
    }

    This will receive all of the orientation changes, and handle the portrait-to-upside-down changes. All that’s left is to flip the gravity.

    func portraitOrientationChange() {
        // Change gravity direction
        gravityBehavior?.gravityDirection = regularGravityVector
    }
    
    func portraitUpsideDownOrientationChange() {
        // Flip our gravity
        gravityBehavior?.gravityDirection = invertedGravityVector
    }

    Perfect! Now we get the falling blocks we wanted.

    demo of animated uiview responding to device rotation




    Putting it all together, we end up with something like

    //
    //  ViewController.swift
    //  Blocks
    //
    //  Created by Matthew Palmer on 11/05/2015.
    //  Copyright (c) 2015 Matthew Palmer. All rights reserved.
    //
    
    import UIKit
    
    class ViewController: UIViewController {
        // MARK: - Blocks
        
        // Our block
        lazy var greenBlock: UIView = {
            let view = UIView(frame: CGRect(x: 50.0, y: 50.0, width: 100.0, height: 100.0))
            view.backgroundColor = UIColor.greenColor()
            return view
        }()
        
        lazy var orangeBlock: UIView = {
            let view = UIView(frame: CGRect(x: 125.0, y: 190.0, width: 50.0, height: 50.0))
            view.backgroundColor = UIColor.orangeColor()
            return view
        }()
        
        
        // MARK: - Dynamics properties
        // Animator for all of the components
        var itemsAnimator: UIDynamicAnimator?
        
        // Gravity for the system
        var gravityBehavior: UIGravityBehavior?
        
        lazy var regularGravityVector: CGVector = {
            CGVector(dx: 0, dy: 1.0)
        }()
        
        lazy var invertedGravityVector: CGVector = {
            CGVector(dx: 0, dy: -1.0)
        }()
        
        // Collisions
        var boundaryCollisionBehavior: UICollisionBehavior?
        
        // Elasticity
        var elasticityBehavior: UIDynamicItemBehavior?
        
        // MARK: - View lifecycle
        override func viewDidLoad() {
            super.viewDidLoad()
            
            // Listen for orientation changes
            NSNotificationCenter.defaultCenter().addObserver(self, selector: "orientationChanged:", name: UIDeviceOrientationDidChangeNotification, object: UIDevice.currentDevice())
            
            // Add our blocks to the view
            view.addSubview(greenBlock)
            view.addSubview(orangeBlock)
            
            let blocks = [greenBlock, orangeBlock]
            
            // Our master item animator
            itemsAnimator = UIDynamicAnimator(referenceView: view)
            
            // The gravity for our system
            gravityBehavior = UIGravityBehavior(items: blocks)
            
            // The collision between our items, and with the boundary of the containing view
            boundaryCollisionBehavior = UICollisionBehavior(items: blocks)
            boundaryCollisionBehavior?.translatesReferenceBoundsIntoBoundary = true
            
            // The elasticity for the blocks
            elasticityBehavior = UIDynamicItemBehavior(items: blocks)
            elasticityBehavior?.elasticity = 0.6
            
            // Add everything
            itemsAnimator?.addBehavior(gravityBehavior)
            itemsAnimator?.addBehavior(boundaryCollisionBehavior)
            itemsAnimator?.addBehavior(elasticityBehavior)
        }
        
        // MARK: - Orientation
        func orientationChanged(notification: NSNotification) {
            if let device = notification.object as? UIDevice {
                switch device.orientation {
                case .Portrait:
                    portraitOrientationChange()
                case .PortraitUpsideDown:
                    portraitUpsideDownOrientationChange()
                default:
                    return
                }
            }
        }
        
        /**
        * This function handles the response when the device rotates into regular portrait orientation.
        */
        func portraitOrientationChange() {
            // Change gravity direction
            gravityBehavior?.gravityDirection = regularGravityVector
        }
        
        /**
        * This function handles the response when the device rotates into upside-down portrait orientation.
        */
        func portraitUpsideDownOrientationChange() {
            // Flip our gravity
            gravityBehavior?.gravityDirection = invertedGravityVector
        }
    
    }
  9. Apple Watch as a Physical Communicator

    In an excellent article on Stratechery, Ben Thompson writes:

    [The demos show] the wearer to interact with his or her physical environment in a way that was not previously possible.

    The Apple Watch just clicked for me.

    The iPhone famously consolidated three things: a phone, an iPod, and an internet communicator. The first two are the ‘safe’ options—things we were already familiar with. The last one was confusing. Nothing reveals that fact more than the original keynote, with enthusiastic cheers for the first two, and slightly confused applause for ‘internet communicator.’

    But the latter was the one that caused the iPhone revolution.

    In the same way, the Apple Watch is three things: a timepiece, a health tracker, and a physical communicator.

    Right now, we’re hearing half-hearted applause for ‘physical communicator.’ Even the phrasing sounds vague and empty.

    What’s more is that it sounds redundant—why would I need a new point of entry to the physical world? I’m not sure, but it’s dangerous to think of the physical world as intractable and immovable. Everyone knows that software is malleable, but it could be that our interaction with the physical could also be moulded. Maybe Apple Watch is adding a new user interface to the tangible.

    It’s terrifying because it’s new. Because it proposes to challenge something really fundamental, really physical. And because it‘s limitless, in exactly the same way ‘internet communicator’ was limitless.

    Right now, the Watch is a key, a wallet, a ticket, a badge, just like the iPhone originally did email, web browsing, and video. But give it a few years—the same time frame it took for the iPhone to become a window to the internet—and the Watch will become a new window to the physical world.

  10. Visit the archive for more posts.