SnoGlobe arrives!

December 18th, 2009 by Chris

Just in time for the holiday our latest iPhone application, SnoGlobe, has made its way through the review process and onto the App Store.

screenshot.png

As part of the holiday-themed postcard designs crafted for Postage this year Brad created an amazing snow globe design. It was one of our favorites out of the seasonal batch and at some point one of us had the idea that having some snowflakes in the globe would be perfect. One thing lead to another and a mad rush to create 3-D snowflakes ensued.

The end result is SnoGlobe, the ultimate snow globe simulation for the iPhone and iPod touch. SnoGlobe replicates a real snow globe with 3-D particle physics powering the snow flakes. You can decorate the background of the globe with your own photos. The flakes react to gravity and the movement of your phone. Turn the globe upside down to let the flakes collect at the top of the globe and then flip it over to watch them sprinkle down to rest at the bottom. If you watch carefully you’ll even notice the flakes get closer and further away from the surface of the screen! If you like you can freeze the scene and share the resulting image with others using email, Facebook or Twitter.

SnoGlobe is an amazing time sink. It is very easy to get lost playing with the flakes and watching them react to your movements. We nearly missed getting this thing in the store because of its captivating movements! Check out the quick video we made of it in action below and grab it for yourself from the App Store for some holiday fun!

Comments Off

iPhone User Interface Projects

December 17th, 2009 by Chris

Brad and I have recently contributed a chapter to a new iPhone book focused on user interface design and experience from Apress – iPhone User Interface Design Projects.

In our chapter we cover much of the process our team went through to create Postage. Along the way we discuss some of the core concepts and models we employed while designing the user experience. There are also plenty of useful tips, tricks and small details that go into any great iPhone application.

Here is a sample of one of the figures from the book showing some of the early mock-ups of Postage :

Figure 19.png

If you are developing iPhone applications you might want to give the book a browse. Several of the other chapters are very interesting as well. My favorite is Jürgen Siebert’s treatise on fonts. He covers all kinds of great info on type, including a detailed anatomy of letterforms. If you ever wanted to start yourself down the path to claim the title of Font Nerd, his chapter would be a great place to start.

You can grab the book at Amazon or find it on the shelves of any book retailer with a decent selection of software development books.

Comments Off

Holiday Sale

December 16th, 2009 by Chris

We are having a holiday sale!

Right now both Postage and Holiday ~ Postage are discounted to celebrate the season.

Postage

Postage is our premium virtual postcard application for the iPhone. With Postage you can choose from over 70 professional postcard designs that you can customize with your own photos and message. After you create your postcard you can share it with your friends and family using email, Facebook or Twitter.

Postage has won numerous awards including an Apple Design Award and most recently Macworld’s 2009 App Gem award. We are sure you’ll love using Postage, so if you haven’t tried it out yet be sure to grab it for the low price of $2.99.

It will only remain at this price for a limited time, so don’t delay.

Screenshot 4.png

Holiday Postage

Holiday ~ Postage is a seasonally themed version of Postage with ten beautiful postcard designs just perfect for the holiday. Why not try sending out a virtual greeting card to your friends and family with Holiday ~ Postage right from your iPhone?

Holiday ~ Postage uses the same engine as its big brother Postage, but is themed for the season and has more holiday postcard designs. Right now you can get it for 50% off its regular price of $1.99 for just $0.99!

4.png

Comments Off

iPhone Animation Sequence

December 11th, 2009 by Jeff

When writing Postage and WORD SPIN we encountered the same problem again and again: the need to chain a sequence of animations together. For example, when the user navigates to the next page we first animate away the controls for the current view, switch views, then animate the controls in for the new view. Initially, we set the UIView delegate and then in our specified selector implementation kicked off the next animation which itself would eventually call back into a completion selector, and so on. But it’s largely the same code over and over, and you either need a bunch of similar looking animationDidStop implementations, or a single implementation that branches based on the animation identifier. For example:

Old Way


- (void) doMoveFromView1ToView2Animation
{
    [app beginIgnoringInteractionEvents];

    [UIView beginAnimations: @"HideView1Animation" context: foo];
    [UIView setAnimationDuration: kDuration];
    [UIView setAnimationDelegate: self];
    [UIView setAnimationDidStopSelector:
        @selector(hideView1AnimationDidStop:finished:context:)];

    [self hideView1Code];

    [UIView commitAnimations];
}

- (void)hideView1AnimationDidStop:(NSString*)animationID
                         finished:(NSNumber*)finished
                          context:(void*)context
{
    [UIView beginAnimations: @"SwapView1AndView2Animation" context: foo];
    [UIView setAnimationDuration: kDuration];
    [UIView setAnimationDelegate: self];
    [UIView setAnimationDidStopSelector:
        @selector(swapView1AndView2AnimationDidStop:finished:context:)];

    [self swapView1AndView2Code];

    [UIView commitAnimations];
}

- (void)swapView1AndView2AnimationDidStop:(NSString*)animationID
                                 finished:(NSNumber*)finished
                                  context:(void*)context
{
    [UIView beginAnimations: @"ShowView2Animation" context: foo];
    [UIView setAnimationDuration: kDuration];
    [UIView setAnimationDelegate: self];
    [UIView setAnimationDidStopSelector:
        @selector(showView2AnimationDidStop:finished:context:)];

    [self showView2Code];

    [UIView commitAnimations];
}

- (void)showView2AnimationDidStop:(NSString*)animationID
                         finished:(NSNumber*)finished
                          context:(void*)context
{
    [app endIgnoringInteractionEvents];
   
    [self doStuff];
}

When we embarked on WORD SPIN it was time to build something to help tackle this problem. I settled on the concept of sequences, where each individual animation is a step in the overall animation sequence. For the user example of moving from one page to the next in Postage, the new code looks like this:

New Way


- (void) doMoveFromView1ToView2Animation
{
    NSMutableArray* steps = [NSMutableArray array];

    [steps addObject: [RSViewAnimationSequenceStep stepWithTarget: self
                                                         selector: @selector(hideView1Code)
                                                         duration: kDuration]];
    [steps addObject: [RSViewAnimationSequenceStep stepWithTarget: self
                                                         selector: @selector(swapView1AndView2Code)
                                                         duration: kDuration]];
    [steps addObject: [RSViewAnimationSequenceStep stepWithTarget: self
                                                         selector: @selector(showView2Code)
                                                         duration: kDuration]];
   
    [[RSSequenceManager sharedManager] invokeSequence: steps];
}

What I really like about this approach is that the entire animation sequence is specified in the same location and it’s clear how many independent steps there are up front, rather than jumping from one place in the code to the next to see what the whole animation will do. Granted, you could almost achieve the same visual effect by refactoring all the “beginAnimation” code into a reusable piece. In fact, that’s how I started.

The fundamental piece of this paradigm is the sequence step. RSViewAnimationSequenceStep inherits from RSSequenceStep, a base class to define the invocation and delegation of the step. RSViewAnimationSequenceStep is primarily a refactoring of the beginAnimation and commitAnimation boiler plate (I’ve removed the definition of the helper, init, and dealloc selectors for brevity):

RSViewAnimationSequenceStep


@interface RSViewAnimationSequenceStep : RSSequenceStep
{
    id      target_;
    SEL     selector_;
    float   duration_;
}

+ (id) stepWithTarget: (id) target selector: (SEL) selector duration: (float) duration;

- (void) invoke;

@end

@implementation RSViewAnimationSequenceStep

// helper, init, and dealloc removed for brevity

- (void) invoke
{
    [UIView beginAnimations: @"RSViewAnimationSequenceStep" context: nil];
    [UIView setAnimationDuration: duration_];
    [UIView setAnimationDelegate: self];
    [UIView setAnimationDidStopSelector:
        @selector(animationDidStop:finished:context:)];

    [target_ performSelector: selector_];

    [UIView commitAnimations];
}

- (void) animationDidStop:(NSString *)animationID
                 finished:(NSNumber *)finished
                  context:(void *)context
{
    // delegate is defined in the base class RSSequenceStep (see below)
    [delegate_ stepCompleted: self];
}

@end

The RSSequenceStep is a simple base class to define the general interface:

RSSequenceStep


@interface RSSequenceStep : NSObject
{
    id  delegate_;
}

@property (nonatomic, assign)   id  delegate;      
    // The object that implements stepCompleted.
       
- (void) invoke;
    // Called to invoke the code necessary for the step.
   
@end

@interface NSObject (RSSequenceStepDelegate)

- (void) stepCompleted: (RSSequenceStep*) step;

@end

RSViewAnimationSequenceStep encapsulates handling the beginning and ending of an animation, and then calls back to a delegate when complete. It is a self contained item that can be used independently. If so desired, we could stop here and have client code declare the RSViewAnimationSequenceStep, set the delegate to self, and achieve a large part of the refactoring. But the steps would still be spread apart in the code. That’s where the RSSequenceManager, and it’s implementation detail class RSSequence, comes into play, as those two handle chaining the steps together to encapsulate the entire animation.

RSSequenceManager


@implementation RSSequenceManager

// things removed for brevity

- (void) invokeSequence: (NSArray*) steps
{
    RSSequence* sequence = [RSSequence sequenceWithSteps: steps delegate: self];

    [sequences_ addObject: sequence];
   
    if ( [sequences_ count] == 1 )
    {
        [sequence invoke];
    }
}

- (void) sequenceCompleted: (RSSequence*) sequence
{
    [sequences_ removeObject: sequence];
   
    if ( [sequences_ count] > 0 )
    {
        [[sequences_ objectAtIndex: 0] invoke];
    }
}
@end

The bulk of the work, however, happens inside the RSSequence class:

RSSequence


@interface RSSequence : NSObject
{
    int         currentStepIndex_;
    NSArray*    steps_;
    id          delegate_;
}

- (id) initWithSteps: (NSArray*) steps delegate: (id) delegate;

- (void) invoke;
    // Called to initiate the sequence.
   
@end

@interface NSObject (RSSequenceDelegate)

- (void) sequenceCompleted: (RSSequence*) sequence;

@end


@implementation RSSequence

- (id) initWithSteps: (NSArray*) steps delegate: (id) delegate;
{
    self = [super init];

    if ( self )
    {
        steps_ = [steps retain];
       
        for ( RSSequenceStep* step in steps_ )
        {
            step.delegate = self;
        }
    }

    return self;
}

- (void) dealloc
{
    [steps_ release];
    [super dealloc];
}

- (void) invoke
{
    [[UIApplication sharedApplication] beginIgnoringInteractionEvents];
   
    currentStepIndex_ = 0;
   
    [self invokeNextStep];
}

- (void) invokeNextStep
{
    if ( currentStepIndex_ < [steps_ count] )
    {
        RSSequenceStep* step = [steps_ objectAtIndex: currentStepIndex_++];
       
        [step invoke];
    }
    else
    {
        [[UIApplication sharedApplication] endIgnoringInteractionEvents];
       
        [delegate_ sequenceCompleted: self];
    }
}

- (void) stepCompleted: (RSSequenceStep*) step
{
    [self invokeNextStep];
}

@end

The sequence manager doesn’t know or care that a sequence is an animation, and a sequence also doesn’t know or care what an individual sequence step does. Those classes only assume that a sequence step’s ending can, but doesn’t have to, come later than its beginning. Given that, we’ve also implemented other sequence step subclasses: one that is a simple selector call, one that encapsulates multiple simultaneous steps, and one that handles openGL animations. I’ve pared the code down a fair bit for this posting, and left out detail — for example, our view animation step handles delays, custom timing functions, and transitions. But the basic idea is all there.

Lastly, Joe Conway over at the Big Nerd Ranch posted a blog about this problem, and described a solution using a subclass of CALayer that calls completion targets for a given animation key. I like his approach because it theoretically handles all the different kinds of animations, and I’ll be thinking about how to work his idea into our sequences.

1 Comment »

New Apps – Word Spin Lite and Holiday ~ Postage

December 8th, 2009 by Chris

We have two new iPhone applications in the store this month that you might want to check out:

Holiday ~ Postage

First, Holiday ~ Postage is a special holiday themed edition of our virtual Postcard application – Postage. It has 10 great new postcard designs and the whole application interface is themed for the season. You’ll love the new snow globe design if you haven’t seen it yet. You can get it on the App Store now for just $1.99

HolidayPostage.png

Word Spin Lite

We have also released Word Spin Lite, a free edition of our highly addictive word game created in partnership with Geospace International

Word Spin Lite has the same engine as the full version of Word Spin and allows you to play challenges that created by your friends or practice the game. You can upgrade Word Spin Lite to the full version right inside the application. After you upgrade you’ll be able to create your own challenges, as well as play the full Solitaire game and compete for a spot on the global leader board.

Its free to try, so go ahead and give it a shot! Here are a couple of challenge codes you can try out with Word Spin Lite :

4 Wheels, 4 Rounds : UNQKQI

8 Wheels, 1 Round : KRRXDX

Click the links above if you are on an iPhone with Word Spin installed, otherwise you can just type in the six letter code into the Challenge screen.

WordSpin.png

2 Comments »