Panic on American ApparelCar in Snow, Part 5Car in Snow, Part 4Car in Snow, Part 3

fill the void

iPhone Tip: Rotating UIView

The iPhone OS’s accelerometer tells me the exact x, y, and z orientation of an iPhone or iPod Touch. Which is freakin’ awesome. To demonstrate how easy it is to leverage, I wrote a bit of code to rotate a UILabel in a simple Utility app. The controller sets itself as the delegate for UIAccelerometer and then responds to the selector accelerometer:didAccelerate:. I started by simply using the exact rotation, but that resulted in a very wobbly text label; so, I added a bit of rounding and animation to dampen it.

// add UIAccelerometerDelegate as a delegate to the controller
// add a UILabel to the XIB and hook it up to the controller
// add QuartzCore framework

// MainViewController.h
@interface MainViewController : UIViewController <UIAccelerometerDelegate> {
	IBOutlet UILabel *textLabel;
}
@end

// MainViewController.m
#import "MainViewController.h"
#import <QuartzCore/QuartzCore.h>

@implementation MainViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
		// Set this controller as the accelerometer's delegate.
		[[UIAccelerometer sharedAccelerometer] setDelegate:self];
    }
    return self;
}

- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
	// Get the rotation in radians.
	CGFloat rotation = (atan2(acceleration.x, acceleration.y) + M_PI);
	// Dampen it a bit.
	float div = 48 / (2 * M_PI);
	rotation = (int)(rotation * div) / div;
	// Animate the movement a bit.
	[UIView beginAnimations:nil context:NULL];
	[UIView setAnimationDuration:.2];
	textLabel.layer.transform = CATransform3DMakeRotation(rotation, 0, 0, 1);
	[UIView commitAnimations];
}

@end

iPhone Tip: Capturing a Shake Event

It’s very easy to detect a shake event in an iPhone app. There are many good posts on StackOverflow about it, but I wanted to consolidate the code into the minimal number of lines. The key is the motionEnded:withEvent: delegate and the view becoming the first responder.

-(BOOL)canBecomeFirstResponder {
    return YES;
}

- (void) viewDidAppear:(BOOL)animated {
	[self becomeFirstResponder];
    [super viewDidAppear:animated];
}

- (void) viewDidDisappear:(BOOL)animated {
	[self resignFirstResponder];
	[super viewDidDisappear:animated];
}

- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event {
	if (event.subtype == UIEventSubtypeMotionShake) {
		// TODO: insert code here.
	}
	[super motionEnded:motion withEvent:event];
}

Obligatory iPad Post

“When the Mac first came out, Newsweek asked me what I [thought] of it. I said: Well, it’s the first personal computer worth criticizing. So at the end of the presentation, Steve came up to me and said: Is the iPhone worth criticizing? And I said: Make the screen five inches by eight inches, and you’ll rule the world.”
- Alan Kay in 2007

“Nothing about the iPad is obviously revolutionary, but it didn’t need to be: the iPhone OS and iPhone hardware are already revolutionary.

Apple already reinvented John’s mobile computing and my input mechanics and novice usability in 2007 with the iPhone. We’ve had the truly magical and revolutionary product this entire time, but we take it for granted now, and we’ve forgotten how awesome it already is.”
- Marco Arment from Tumblr and Instapaper

“The iPad as a particular device is not necessarily the future of computing. But as an ideology, I think it just might be. In hindsight, I think arguments over ‘why would I buy this if I already have a phone and a laptop?’ are going to seem as silly as ‘why would I buy an iPod if it has less space than a Nomad?’”
- Steven Frank from Panic

Not exactly filling the void with an iPad post, particularly one that’s two weeks late to the party and starts with what smarter people have already said. I blame Things for not being more insistent.

I agree that Apple’s iPad is the next step in computing: simplified computing. Yes, it has its shortcomings (inherent to a 1.0 release, which the iPhone had only three years ago), but it keeps with the design decisions that made the iPhone/iPod Touch ridiculously popular.

To illustrate the need, let me tell you about the “Check disc” incident. Over Christmas, my Dad subscribed to the New York Times Crossword Puzzle. The NYT doesn’t have an online puzzle component, so he had to download Across Lite, a third party Windows app. He called me after using it for a couple days about a “disc” issue. Whenever he tried to save the day’s puzzle, the app displayed, “Cannot write to file. Check disc.” It was such a weird error that I wanted to see it for myself. With VMWare Fusion on my Mac, I installed Across Lite and got the same error within a minute. I didn’t actually figure out what the problem was (read-only directory?); instead, I simply told my Dad how to use the “Save As…” option to save the puzzle to the Desktop. Problem solved.

But the larger problem is not solved. The incident is a perfect example of the abstraction problems that current computing environments have. They want to deal in apps and documents and photos, but they still break these abstractions daily. Windows gives me app shortcuts available from the Start menu, but those are a mediocre hack to abstract away the monstrous Program Files folder. Mac apps are nicely treated as atomic objects (even though they are folders), but people still run them out of read-only DMGs, leading to equally confusing error messages. All these semi-porous abstractions lead to a lot of unnecessary confusion.

The iPhone OS enforces the abstraction to a much better degree, and we’ve seen the results: over two billion apps downloaded on seventy million devices in eighteen months. All these little apps are islands of data, a per-app version of the Newton’s data soup platform. The iPad simply extends this OS to a larger surface.

I want one.


Cocoa Tip: NSImage Composites

Recently, I wanted to composite together two images, much like Tweetie’s retweet UI for avatars: display the main icon in its original size but overlay a second icon smaller and offset. Turns out to be only a couple lines of code using NSImage:

NSImage *mainIcon = [NSImage imageNamed:@"main_icon"];
NSImage *overlayIcon = [NSImage imageNamed:@"overlay_icon"];
[mainIcon lockFocus];
[[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh];
[overlayIcon drawInRect:NSMakeRect([mainIcon size].width / 2, 0, [mainIcon size].width / 2, [mainIcon size].width / 2) fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];
[mainIcon unlockFocus];

Creating a Menu Bar Item

On my MacBook Pro, I have a lot of items in the menu bar: Tweetie, LittleSnapper, Jing, Evernote, BusySync, MobileMe, along with the standard set. Recently, when I needed to make my own, I started wondering what they are. Actual apps or app components? Activity Monitor confirmed that most are separate applications, although Tweetie’s is just a component. Good, so how do I make one?

All I had to do is add a single row to Info.plist: set LSUIElement to true. The other code is boilerplate, creating a controller in Xcode and hooking up some outlets in Interface Builder. I created a quick sample project on Google Code under MenuBarItem (screenshot below). Thanks again to Glyphish for an awesome set of free icons, including the pictured coffee mug.


← Before After →