Checking out the new stuff

Taking advantage of a weekend trip to Syracuse, home of the nearest Apple Store, I test drove Apple’s latest products.

Apple Watch

I tried on two models: the stainless steel with Milanese loop and the Space Gray Sport. When I specified which versions I wanted to try I foolishly forgot to specify size, so both of the ones the Apple guy brought out were 42mm. This size turned out to be a bit large for my scrawny wrists. Still, I wear a fairly big watch now and I might be able to just barely get away with it, which would be nice since the 42mm features longer battery life.

A photo posted by @duc on

The Milanese loop can be made surprisingly tight, which is important for getting accurate heart rate readings. The magnet is strong and the band itself is quite comfortable. Not surprisingly, the fluoroelastomer band is also very comfortable. Unfortunately these units only ran a demo loop that had no interaction at all. A couple times during the demo you could feel the haptic tap used to notify you. My first impression is that it needs to be stronger if I’m to notice it while doing things throughout the day.

There were usable demo models in the store, but they were fixed to a base which obviously doesn’t give you a faithful representation of daily Apple Watch usage. Still, playing with the interface, getting a feel for how quickly the digital crown scrolls content, and experimenting with Force Touch was very informative.

The digital crown feels great. While you can always scroll by dragging your finger, in most circumstances you’ll probably want it out of the way and just use the crown. You also use it zoom in and out on the app selection screen. Some people have complained that the app view is zoomed out too far by default, with the circles too small to be tappable. I found this screen usable, but I agree: it’d be nice if the default zoom was a little further in.

In my brief time with the demo watch the only place I could find to trigger a Force Touch was in the Messages app, where performing one lets you compose a new message. I found myself trying to Force Touch on every screen and was disappointed when nothing happened most of the time. I imagine that becoming more familiar with the interface will reinforce which screens are Force Touchable and which aren’t, but for now it’s rather confusing.

Trying the Watch was fun and I can see the appeal of having notifications on your wrist and being able to perform simple tasks faster than you might be able to on a phone. Still, I expect evolution in thinness and functionality to happen quickly, which reinforces my decision to stand by this generation and wait until next year at the earliest.

MacBook

I also played with the new MacBook, which is an incredibly slim and beautiful device. The case is very sturdy for something so thin. The keyboard’s shallow travel isn’t great, but my wife and I both found that typing on it was fine. You probably get used to it. For developing apps and editing photos I need the MacBook Pro (though this MacBook is probably way more powerful than my 2008 MBP), but I would absolutely love to have something close to a Pro’s power in the new MacBook’s form factor. I’d happily sacrifice the ports. All other laptops seem ludicrously fat and heavy in comparison.

I was incredibly skeptical of the Force Touch trackpad and I lamented its introduction to the 13″ MacBook Pro line, but fake-clicking is as convincing as mechanical clicking. It’s incredibly good. Pushing harder to trigger a “force click” is pretty cool too. The click from a force touch is firmer. If you ramp up the pressure slowly enough when force clicking over a word, you can control the size of the popover that displays the word’s definition until it gets to full size. It’s a neat effect.

Type inference fail

Before I begin I should note that I’ve become a fan of Swift’s trailing closure syntax and that’s what you’ll see here. There are a lot of ways to declare a closure, though, and I’m not particularly religious about my choice.

Also, this example applies to Swift 1.2 from Xcode 6.3 Beta 2. The language is still very much in flux.

When you’re using sort or sorted the compiler should know the argument types passed to the closure that does the comparison. The Swift documentation describes this:

The sorted function takes two arguments:

  • An array of values of a known type.
  • A closure that takes two arguments of the same type as the array’s contents, and returns a Bool value to say whether the first value should appear before or after the second value once the values are sorted. The sorting closure needs to return true if the first value should appear before the second value, and false otherwise.

This lets you write terse closures that don’t have to spell out the array type involved:

So you’d think it would work for slightly more complex data types (PhotoKit’s PHAsset in this case):

But I get this error:

Cannot find an overload for 'sorted' that accepts an argument of list of type '([PHAsset], (_,_) -> _)'

So instead I have to declare types for everything like I’m still at my C/C++ day job:

The same thing happens with sort.

It’s not a big deal, but I’ve come to enjoy Swift’s syntactic sugar and my slight OCD nature doesn’t like having this closure declared differently from the others in my code.

Swift compiler errors suck

A lot of the reticence I see for adopting Swift has been less about the language and more about the tools: long compile times, SourceKit constantly crashing, no refactoring, really slow autocomplete, and incomprehensible compiler errors. It’s that last one that’s been annoying the crap out of me lately (forgive my ancient non-Retina display):

CGRect: Extra argument 'width' in call

“Extra argument ‘width’ in call” doesn’t make any sense since init(x: CGFloat, y: CGFloat, width: CGFloat, height: CGFloat) is definitely in CGGeometry.h. The actual problem here is that I renamed index to number and forgot to change it for the y argument. No variable named index exists and it would’ve been nice if the error reflected that.

Still, I don’t regret implementing my first iOS project in Swift. It’s modern, incorporates aspects of functional programming, and is generally fun to code in. I’m reasonably confident many of the tools issues will be resolved as the language matures.

Panning multiple scroll views simultaneously

UIScrollView provides a lot of control over the way you can present content to the user, but I have a need for one gesture recognizer to pan  multiple views simultaneously. You can probably use scrollRectToVisible to achieve this by moving the content view programmatically, but implementing the bouncy physics via that method seems painful. Plus I have other customizations I want to make.

In search of a solution, I found Ole Begemann’s outstanding post Understanding UIScrollView on reproducing the functionality of UIScrollView. The idea behind the article was to achieve a better understanding of how this Cocoa feature works, but for this iOS newbie it was a way to produce the behavior I needed.

The original post is excellent so there’s little point in me saying much else about it, other than that I am working in Swift and thus needed an implementation in that language. You can get my implementation on GitHub. I have not yet implemented the inertial scrolling, bouncing and rubber banding that some of Ole’s readers contributed, but I’ll update this post when that work is done.

The benefit of making your own view is that you can determine how that view handles gestures (actually, you can still do this if you subclass UIScrollView, but I’ll get into that later). In this case, I don’t want my custom scroll view to handle gestures at all. So while Ole’s class calls addGestureRecognizer to set one of its own methods as its gesture action handler, my SwiftScrollView.handlePanGesture() is called by its superview (in the example on GitHub this superview is just the ViewController):

And of course the superview sets a UIPanGestureRecognizer so its version of handlePanGesture gets called:

There you have it: one gesture recognizer scrolling two views. If you run the project I have up on GitHub you can see this in action. There’s more stuff I want to do with this and I’ll share that soon.

P.S.: If you want to do something like this but still want features of UIScrollView, you can subclass it and override addGestureRecognizer so it can’t set a pan recognizer:

Pretty crude, but it works. You might also be able to do something like

after self.panGestureRecognizer is set, but I haven’t tried this.

I finished the Swift book

It only took two months, but I finally finished The Swift Programming Language, Apple’s guide to their new app development language (I linked the web version but actually read the iBooks version so I could highlight and annotate). As far as documentation goes, it’s certainly better than most: informal at times to make it more readable, well thought out examples, really nicely formatted. It seems introductory enough for the beginning programmer (though probably not for someone who has never coded before) but it’s also littered with comparisons to C and Objective-C to provide context for more experienced developers.

A lot of books will be written to teach Swift, but unless you’re totally new to programming, I wouldn’t bother buying one. Apple’s book introduces the language nicely, so I’d save my money for the inevitable slew of texts that’ll cover best practices (once the community establishes best practices) and advanced topics.

In the meantime, make sure you follow Apple’s Swift blog for updates on the language and explorations of features that go a little deeper than their book. If you’re ready for more detailed discussion of the language, I recently found the amazing Airspeed Velocity, which often goes all out in explaining things like nil coalescing . Mattt Thompson has been writing about Cocoa and Objective-C for years at NSHipster and has more recently begun diving into Swift with stuff like this great article on literal convertibles.

There’s a lot of wonderful writing out there already and we’re not even at Swift 1.0 yet. How many great issues on Swift will objc.io put out in the months to come? How cool will it be when Brent Simmons details his journey with Swift on Inessential? I can’t wait for it all.

Managing the work

Joel Spolsky used to be better known for blogging about software than for his company and its products. His posts on coding and hiring were pretty influential, but what made one of the biggest impacts on my life was a post on the desks that Fog Creek gave their employees. I’m not lucky enough to get such luxury paid for at my job, but I wanted a standing desk badly enough that I bought myself a Steelcase Series 7 on Joel’s recommendation, figuring he must have done the research to determine that those were the best (I spend at least 8 hours a day at that desk, after all; love the desk, by the way).

I had read his blog for years before I actually had a chance to use FogBugz. We used it at work and while I don’t particularly care for any feature-planning and bug-tracking tools, it was relatively straightforward and did most of the things we needed. We’ve since abandoned it at my job, but when it came time for me to decide on a tool to help plan my side projects, FogBugz immediately came to mind.

It helps immensely that they have a Students and Startups Edition that allows up to two people to use their products for free. It’s a great approach: if the company becomes successful and grows, the goodwill and ecosystem lock-in go a long way in helping that company decide to start paying for the products. I don’t expect to get there myself. Everything I hope to find time to work on will mostly be for fun.