• Google's Catfish Caller

    Jason Snell puts a fine point on something that bothered me about the Google Duplex announcement yesterday.

    One of the things about the demo that was distasteful is that it felt like a high-tech prank call, a Google-powered “Crank Yankers”: We were, at some level, meant to laugh at the people on the other end of the line for being fooled into thinking they were talking to a real human being, thanks to the inserted “ums” and sentences ending in uptalk. They were the butt of a joke, made by one of the most powerful companies in the world.

    It isn’t just distasteful, it comes off as tone-deaf given our current media environment. We’re living in a reality of cosplay journalists going undercover trying to expose real journalists, conspiracy theories broadcast to huge audiences, and disingenuous ‘intellactuals’ portraying themselves as martyrs. And along comes Google, building impressive products without any forethought of how it will be used to malevolent ends. A disclosure should be in there. The fake human pauses and inflections should be out. The future here needs to be robot assistants, not passable human clones.

  • Samsung VR for iOS

    We’ve released a new product at work today!

    Samsung VR is now available for iOS. There’s a huge amount of immersive video content available online and the barrier to creating has never been lower for both professionals and hobbyists. Samsung VR is the best way to present and discover immersive video, I hope you’ll enjoy using the app as much as I’ve enjoyed creating it!

  • Apollo + PromiseKit

    Today we’re looking at [the very cool] GraphQL and a popular iOS client library for interfacing with GraphQL servers. Being that the rest of the application in question is already chock-full of promises, it made sense to want an option for using promises rather than Apollo’s GraphQLQueryWatcher + callbacks. The good news is that Apollo has support for promises, the bad news is that they wrote it themselves.

    Love it when a framework recreates another popular library and we spend time writing plumbing like this. The simplicity of this little bit of code obscures how annoying this really is. Now with multiple declarations of the same class in this project, we have lots of compiler hinting and needless explicit module qualifications that could be avoided by not reinventing the wheel. If you’re creating a library for iOS and want to include Promise functionality, please use PromiseKit.

    Of course, the real answer is a set of concurrency primitives in Swift. Soon.

    import Apollo
    import PromiseKit
    
    extension Apollo.Promise {
        func pkPromise() -> PromiseKit.Promise<Value> {
            return PromiseKit.Promise(resolvers: { (fulfill, reject) in
                self.andThen({ (v) in
                    fulfill(v)
                }).catch({ (err) in
                    reject(err)
                })
            })
        }
    }
    
  • Real Screen Lock in High Sierra

    Glad to finally get Keychain Access out of my menu bar

    Finally.

  • UIBarButtonItem Sizing in iOS 11

    When setting UIBarButtonItem in previous versions of iOS I’ve been able to reliably control the size of buttons by using a UIButton initialized with a frame. In iOS 11 this has changed as UINavigationItem now [finally] uses AutoLayout.

    The easy solve for this, using SnapKit looks like:

    let button = UIButton()
    button.setImage(UIImage(named: "btn-img"), for: .normal)
    button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
    let barItem = UIBarButtonItem(customView: button)
    
    barItem.customView?.snp.makeConstraints({ (make) in
      make.width.equalTo(22)
      make.height.equalTo(22)
    })
    

    And if you’re using vanilla AutoLayout:

    let button = UIButton()
    button.setImage(UIImage(named: "btn-img"), for: .normal)
    button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
    let barItem = UIBarButtonItem(customView: button)
    
    let width = barItem.customView?.widthAnchor.constraint(equalToConstant: 22)
    width.isActive = true
    let height = barItem.customView?.heightAnchor.constraint(equalToConstant: 22)
    height.isActive = true
    

    Extra bonus: you can also safely connect your bar buttons to custom navigation item titleView’s to avoid buttons overlaying your title content. This is a great improvement to have in iOS 11 and should obviate the need for the UINavigationBar hacking of yore.