LEGO iPhone dock 1.0

LEGO dockWhen the iPhone 5 was announced last September, it was the first iPhone to ship without an Apple dock, and also the first iPhone that would not fit via an adapter in Apple’s so-called “Universal” dock. As an iOS developer, it’s useful for me to keep my phones upright and charging at my desk, ready to be debugged via Xcode, so I’ve always bought a dock for each iPhone generation. Furthermore I’ve always gone with Apple’s docks because they were available on launch, cheap enough, compact, and work well. But with the iPhone 5 for the first time I had to look for 3rd party docking options. Then I stumbled upon these directions for a LEGO phone dock that would integrate a Lightning cable. Because I love LEGO’s and the parts were cheaper than any other dock, I went ahead and ordered the parts from LEGO’s Pick-A-Brick store (I had to make some substitutions due to availability).

IMG_2373
The heart of the dock is the 2 bricks with vertical clips that hold the Lightning cable firmly in place.

IMG_2368Another nice touch is having two grill pieces that don’t block the speaker and microphone, so that you can use the phone in speaker phone mode while docked. I also like that the front portions are smoothly tiled over with nary a stud in sight.

IMG_2365

Next up: revisions to make LEGO dock 1.1

Standing Desk 1.0

Standing positionEarly this year I purchased my first standing desk. Originally I was looking at treadmill desks as a way to help get in shape despite the long hours I spend at my desk each day. I didn’t feel like I had the time for a DIY project, so I was considering pre-built solutions such as this LifeSpan Fitness treadmill desk. Their desk seemed nice, but I had 2 problems with it. First it is fixed in height and so could never be used as a sitting desk, and second I already have 3 desks in my office that I like and the last thing I needed was a 4th desk.

The other reason I was looking at treadmill desks was because sitting at my desk was becoming increasingly more uncomfortable. I’ve been programming professionally for 15 years and sitting long hours each day the entire time. Up until last year, I would only get sore after more than 10 or 12 hours of sitting. But this past year that dropped to 8 and then 6 and then 4 hours or even less. Changing positions and getting up for stretching breaks (which I do regularly) wasn’t helping much. Sitting at my desk had literally become (forgive the pun) a pain in the ass. Of course to address this problem I didn’t need a treadmill, just a standing desk. But I figured that standing all day would quickly become just as painful as sitting all day, so what I really needed was an adjustable desk. (LifeSpan and other companies also sell standing desk treadmills without the desk, so I could always add a treadmill later.)

So after some research I decided to get a GeekDesk without a top and reuse the existing glass top from one of my desks, and just swap out the existing frame for the GeekDesk one. I chose the more expensive Max version mainly for the programmable presets, and I chose a small frame to fit one of my two 120 cm desks (I could have gotten a large frame for my 160 cm desk).  Using my own top saved me $264 between reduced price and reduced shipping.

GeekDesk Max frameCustomer service at GeekDesk was great and my desk arrived promptly. You assemble it yourself, but that’s easy and the build quality is great.  Adding your own glass top is probably even easier than adding your own wood top because you can assemble the desk upright and merely set the glass top in place. The one thing you need are little rubber / silicone pads to put in between the metal frame and the glass top. These cushion the top but also provide the necessary friction so that the top will not slide sideways with pressure. Fortunately I already had these from my previous desk frame.

When the desk is in seated position the before (above) and after (below) appearance is practically unchanged.

Before
After

In Use

At first, I was changing positions every 30 minutes using a timer to remind me. I rotated between 3 positions: sitting in a chair, standing, and sitting on a balance ball (with the desk in its lowest position). Changing so frequently was no doubt overkill and most of the time I had trouble focusing properly while standing. Working while sitting is a hard habit to break. 9 months later I still sit most of the day, but once or twice a day I will move the desk  into standing position and stand for a while. I probably ought to change more often. I still find it hard to concentrate while standing, so whenever I’m faced with a particularly difficult problem to solve, I always have an urge to sit. Overall I’m very happy with the purchase and glad I have the option to shift my work position upon demand. Maybe next year will be the year I am able to add a treadmill into the mix.

Lowest position

CocoaConf San Jose wrap-up

This past weekend I had the pleasure of attending and speaking at CocoaConf San Jose. This was the 6th CocoaConf event I’ve attended, and I believe it was one of the best. Highlights for me included:

  • Matt Drance‘s opening keynote where he discussed the importance of people in our work: our customers (users), our co-workers, and ourselves. This is something that we as engineers can often lose sight of.
  • Jaimee Newberry‘s session on brainstorming. Jaimee is a fantastic speaker and always fun to watch, and there was plenty of info on how to manage and get the most out of brainstorming sessions, which I’d like to try on my next project.
  • Ben Lachman‘s session on prototyping, which covered a variety of tools and workflows and included a demo of the yet to be released Briefs 2 (which I plan on buying as soon as it is available. Seriously, just take my money already!).
  • Marcus Zarra‘s session on the MVC-N design pattern, which contained a strong admonition against relying on 3rd party code (especially networking code). This is going to change how I approach the next client project I manage. This talk alone made attending the conference worthwhile.
  • Daniel Pasco‘s session on the long road and various pitfalls encountered in transforming his company, Black Pixel, from a client-work company into a product company (Black Pixel makes the excellent Kaleidoscope 2 — you should buy it). Valuable lessons for anyone seeking to go indie.

I presented 2 talks of my own. Thursday evening I delivered a talk on UICollectionView. This was the 4th (and probably final) time I delivered this talk over the past 6 months. The sample app (which contains 5 different layouts and multiple examples of advanced customizations) is available on GitHub here, while the slides can be downloaded here.

photo pinch

Saturday morning I presented “Animation: From 0 to Awesome in 90 Minutes”, which is an animation talk that begins with some design principles of animation (drawn from Phil Letourneau’s portion of our joint animation session at Renaissance), proceeds to discuss UIKit and Core Animation (and the limitations of UIKit), then takes a close-up look at flipping and folding animations, and wraps up with some general graphical performance tips. This talk is sort of an evolution of both the Renaissance talk and my Enter The Matrix: Reloaded sessions from 2012, and yet is also its own thing. I debuted it last month at CocoaConf DC and this was its second iteration. The sample app is available on GitHub here, while the slides are available for download here. My favorite portion of the app is the touch-enabled timing curve widget that lets you create custom cubic bezier curves by dragging 2 control points (and shows you their values). I think that was also one of the big takeaways from the talk: that you can have an animation overshoot its endpoint and then snap back by simply applying the right timing curve to a basic animation with no need for multiple or keyframe animations.

Timing curve

This wraps up the CocoaConf Spring Tour and my own 3 conference “Spring Tour” as well. I plan to take the summer off from speaking and pick it up again in the Fall.

Speaker kit

Gear
I thought I might list the gear I pack when presenting at conferences

  • 15″ retina MacBook Pro — my favorite Mac ever. Great for presenting, coding, and preparing slide decks
  • iPhone 5 (AT&T) — my constant companion. Tethering via Personal Hotspot usually beats hotel / conference WiFi every time. Also, I often run Presentation Clock on it while I’m speaking to help me budget my time (propped up by a Glif).
  • iPad mini with Verizon LTE — often my demo device. The non-retina screen actually makes for a better presentation device. Also an alternate tethering source for internet. Having both AT&T and Verizon as data options helps cover all the bases. Recently I’ve had luck running demos on the iPad mini while displaying via AirPlay and Reflector.app back onto my MacBook all driven by the iPad’s Personal Hotspot. This lets me avoid Xcode and the iOS Simulator during presentations.
  • Kensington wireless presenter (with extra lithium batteries) — rock solid and works great and means I’m not tied to my laptop or the podium.
  • 3 x 4 GB USB thumb drives — for distributing slides and sample code at the beginning of the talk (have I mentioned that conference WiFi is usually terrible?)
  • Mophie juice pack with charging cable — I could probably leave this at home, but it’s nice to have a backup and offering power is a great way to meet people.
  • 2 Lightning to USB cables — for charging phone and iPad simultaneously. Or for debugging (perhaps running Instruments on) an iOS device during a demo.
  • 2 x 12W USB Power Adapter — why would I cart these larger iPad chargers around when traveling? Well I figure you often only get a limited amount of time with an outlet, so you need to make that time count. For that reason I actually upgraded to the 12W adapters (the ones that come with the iPad 4) from the 10W adapters that accompanied the first 3 iPads, merely for the modest gain in charging time. Having 2 means I can charge the iPad and iPhone simultaneously or else the iPad and the Mophie (typically what I do overnight)
  • 1 x 5W USB Power Adaptor — so why bring this one at all? Well, I hate having to remember to swap devices between a limited number of chargers. This allows me to charge my iPhone plus the iPad and the Mophie overnight, so they all start each day fully charged.
  • 4 outlet portable power strip — great for many hotel rooms that often offer only a single outlet in any one place. This lets me plug in all 3 chargers plus charge my MacBook.
  • Lightning to VGA Adapter — in case I need to do VGA out directly from my iPhone or iPad. This is strictly a contingency plan. But also nice that you can do so while debugging or running Instruments via the integrated Lightning port (this used to be a feature limited to the HDMI adapter).
  • mini-displayPort to VGA adapter — for connecting my MacBook to the projector. Typically the conference always provides these but you should always carry your own.
  • MagSafe to MagSafe 2 Converter — in case the power adapter at the podium / presenter’s table is the original MagSafe. Lately though, conferences have been supplying both flavors!
  • Thunderbolt to Ethernet adapter — this is really more of a WWDC thing, but you never know when you’ll need access to ethernet.
  • Lightning to 30-pin Adapter — I’m only carrying Lightning devices and cables, but this is just in case I need to charge from a 30-pin cable (perhaps when riding in a car; I haven’t upgraded my car chargers to Lightning since my wife is still on an iPhone 4S)

So that’s what I’m currently carrying to conferences. I enjoy the convenience of leaving my full-sized iPads at home and only having to bring Lightning-flavor accessories. What are you carrying to conferences?

A potential pitfall of CGRectIntegral

This morning while I was checking an app for misaligned elements, I happened upon a misaligned button. (If you’re not using either the iOS Simulator or Instruments to check your app for misaligned images, you should be, but that’s a post for another day.)

Checking the code it was obvious to me where the problem was.

backButton.frame = CGRectMake(5, (navigationBar.bounds.size.height
    - imageBack.size.height)/2, imageBack.size.width,
    imageBack.size.height);

Centering code is especially prone to pixel misalignment. In this case imageBack has a size of (50, 29) while the navigationBar has a height of 44 points. The code above generates a rect with origin = (5, 7.5) and size = (50, 29). So the image ends up vertically misaligned, which in turn makes the child text label inside also misaligned, and hence they show up painted in magenta when the Color Misaligned Images option is checked in the iOS Simulator Debug menu.

This looks like a job for CGRectIntegral, right? But when I change the code to this:

backButton.frame  = CGRectIntegral(CGRectMake(5, 
    (navigationBar.bounds.size.height - imageBack.size.height)/2,
    imageBack.size.width, imageBack.size.height));

I end up with this:

The button is no longer misaligned, but it is now being stretched (hence the yellow wash). Debugging shows that CGRectIntegral has converted the input rect of (5, 7.5) x (50, 29) into (5, 7) x (50, 30). So now the image is being stretched vertically by 1 point. That might be fine for UILabel but not for an image.

The other issue with using CGRectIntegral is that the original rect is actually fine for retina devices because they have 2 pixels per point, so a value of 7.5 actually falls on a pixel boundary, and is the optimal centering for this image. If we adjusted it to origin.y = 7 (without stretching) then it would be 2 pixels closer to the top than to the bottom on a retina device.

I’ve written some helper functions to correctly pixel align rectangles (not point align) for both retina and non-retina screens, and posted them in this gist.

Under non-retina it would convert the rectangle to (5, 7) x (50,29) to pixel align it without stretching, while under retina it would leave the rectangle unmodified at (5, 7.5) x (50, 29).

This finally clears the magenta (alignment) and yellow (stretch) washes from the button:

Addendum

According to the Apple Documentation for CGRectIntegral:

A rectangle with the smallest integer values for its origin and size that contains the source rectangle. That is, given a rectangle with fractional origin or size values, CGRectIntegral rounds the rectangle’s origin downward and its size upward to the nearest whole integers, such that the result contains the original rectangle.

The fractional origin of (5, 7.5) is rounded downward to (5, 7), but I initially thought the size would be left unmodified (not rounded up) because it already comprises 2 whole integers. But that wouldn’t contain the original rectangle, whose lower right corner is positioned at (55, 36.5). In order to contain the original rectangle, the height has to be increased by 1 point from 29 to 30.

How to Add a Decoration View to a UICollectionView

Decoration views are one of the great new features of collection views.  Unlike cells and supplementary views (e.g. headers and footers), decoration views are layout-driven rather than data-driven.  You can think of them as the shelves in the iBooks Store interface.  Background views are another good candidate for implementing as decoration views.

So how exactly do you add decoration views to your collection view?  It’s actually pretty simple.

  1. Create your decoration view.  It should be a subclass of UICollectionReusableView.
  2. Create your own UICollectionViewLayout subclass if you don’t already have one.  This can be a subclass of UICollectionViewFlowLayout if that’s what you’re using.
  3. Register your decoration view with your layout either by class name or nib.
  4. Return the appropriate attributes for your decoration view in layoutAttributesForElementsInRect:
  5. Implement layoutAttributesForDecorationViewOfKind:atIndexPath: to return attributes for the specified decoration view.


In my sample project IntroducingCollectionViews, the first layout, GridLayout, is an iBooks Store-style layout derived from UICollectionViewFlowLayout.  The layout has shelves underneath each row of cells that are implemented as decoration views.  I will go through the steps above to show how I implemented the shelf views in the GridLayout class.

Create the decoration view

I created a ShelfView class derived from UICollectionReusableView.  It’s a very simple view (no subviews) — I just set backgroundColor to a color from a pattern image and add a drop shadow.  (Performance tip: I set the shadowPath for the drop shadow on the backing layer.  See here for why that’s important.)

Subclass UICollectionViewLayout

I created GridLayout as a subclass of UICollectionViewFlowLayout.  The superclass handles the heavy lifting of positioning all the cells and headers and footers, but I have to handle the decoration views.

Register the decoration view

In the init method for GridLayout I register the shelf view by class.

[self registerClass:[ShelfView class] forDecorationViewOfKind:
    [ShelfView kind]]

(Where kind is a convenience class method I added to return the kind string. Kind becomes important when you have multiple decoration view classes in your collection view.)

Implement layoutAttributesForElementsInRect:

This method is the meat of a layout.  It’s where the layout tells the collection view about all items (cells, supplementary views, and decoration views) that are to appear within a given rect (generally the current visible rect based on the collection view’s current contentOffset).  The collection view in turn takes over instantiating (or reusing) all necessary views and setting their position, size, and other visible characteristics (alpha, transform, zIndex, etc.).

Because I’m deriving from UICollectionViewFlowLayout, I can just call super to get the attributes for all the cells and supplementary views.  I just need to add the decoration views (if any) to that array.  But in order to know which decoration views might fall within a given rect, I need to do some calculations ahead of time.  To do that I need to override prepareLayout.  This is the method that gets called every time the layout becomes invalidated and is where you can calculate where all the collection elements should go.

In prepareLayout I calculate where the shelves will go (don’t forget to call super).  Unfortunately, this means replicating much of the flow layout positioning since I want to position each shelf directly under each row (line) of speakers (actually each shelf goes under the speaker name label of each SpeakerCell).  I calculate the frame of every shelf rect in the entire content area and store them in a dictionary keyed on index path where section is of course the section the shelf resides in and row is the 0-based index of the shelf within each section moving top to bottom. (This will be important when it’s time to implement layoutAttributesForDecorationViewOfKind:atIndexPath:)

Meanwhile, back in layoutAttributesForElementsInRect: I of course call super and then I enumerate through all my shelf rects and for any shelf rect that intersects with the specified rect (meaning a decoration view should appear at that position), I create a set of layout attributes for that decoration view and add it to the array of attributes returned by super.  To create the attributes I call

[UICollectionViewLayoutAttributes 
     layoutAttributesForDecorationViewOfKind:[ShelfView kind] 
                               withIndexPath:key]

Where I just pass in the kind and the index path (which happens to be the key of the dictionary I’m enumerating through).  Then I set the frame to be the rect I have stored and also set zIndex to 0 (I set zIndex to be 1 on all the cells and supplementary views to make sure they appear in front of the shelves).

Implement layoutAttributesForDecorationViewOfKind:atIndexPath:

This one is pretty easy.  Because I stored my shelf rects in a dictionary keyed on index path, I just use the passed index path to fetch the shelf rect and then I just create the attributes exactly as I did for layoutAttributesForElementsInRect:  (Actually I have yet to see this particular method ever get called.  I have a breakpoint set on it and have never had it be triggered.)

Summary

And that’s what it takes to add decoration views to a collection view.  Decoration views are a cool new feature of collection views and are just one of the improvements of UICollectionView over its predecessor for data display on iOS, UITableView.

Once again, the sample project is on GitHub here. The wood paneling backgrounds are part of a set of retina-ready repeatable assets by Glyphish.

Go forth and make amazing collection view layouts!

Hello World

I envision this as a place for me to write about topics other than code- most likely tech, LEGOs, and the iOS programming community; i.e. things I wish to write about, but which I don’t feel belong on markpospesel.com.

Want $100 off early bird registration for Renaissance?

Then I’ve got a discount code for you: use “mpospese” (my Twitter and ADN handle), or just use this direct link.  The code is good through the end of November and gets you into Renaissance for just $500.

Did I mention that there’s going to be a live concert by The Smule Band?  These are the guys behind Ocarina, Leaf Trombone, Magic Piano, and several other apps that turn iOS devices into musical instruments.  Ocarina holds a special place in my heart because using it for the first time was sort of a watershed moment for me in my career as a developer.  I had already been programming for mobile devices for 9 years at that point, but had never seen anything as creative as Ocarina – a device that transformed a phone into a multi-touch wind instrument (you blow past or into the microphone)!  I was already tinkering with the iPhone SDK at that point, but that was when I knew that I really, really wanted to focus on the iPhone platform.  Anyway, as you can tell I’m super excited to see them perform and hope to be able to chat with their team afterward.

The rest of the speaker lineup (myself included) is incredibly diverse and covers pretty much all the aspects of creating apps and running a business of creating apps in today’s market.  It’s a great time to be a developer, designer, or businessperson (or all three), and I plan on learning everything I can that week, especially in the areas that typically fall outside of my comfort zone.

Renaissance

The Art And Science Of Apps


Tim Burks and Bill Dudney are collaborating to put on a new conference for App Makers early next year in San Francisco: Renaissance.  The conference aims to be (roughly) equal parts design, business, and technology.  This is a 3-day single track conference, so you don’t have to miss anything.  The entire speaker roster has yet to be announced, but already includes folks like Daniel Pasco, Rob Rhyne, Brent Simmons, James Dempsey, Chris Clark, and Matt Drance.

I am proud to announce that I will be presenting a session on animation (the technical half) in conjunction with Phil Letourneau of Black Pixel (the design half).  I’m really excited about the session format (50/50 design/technology).

Early bird tickets are available through the end of November.  Even better, for $200 more you can get a combo Renaissance / CocoaConf ticket that is good for Renaissance plus any 2013 CocoaConf conference.  There are four confirmed dates/cities for next Spring (Chicago, DC, San Jose, and Dallas) with more planned for the Fall.

Personally I think this conference is going to be epic.  If you’re an indie, startup, or small company iOS App Maker, you’ll especially want to be there.  The main sessions look great and cover a wide variety of topics, and I’m certain all the informal breakout sessions and after hours conversations will be fantastic.

Update: Use code “mpospese” to register by November 30 and receive an extra $100 off the early bird price!