Friday, October 22, 2010

Could Apple's App Store Lead to a More Open App Ecosystem?

The upcoming App store for Mac seems to have the internet in a mini-uproar. There seems to be a general fear that this is the narrow point of the wedge. That Apple's long term plan is to lock-down the Mac, the same way they have locked down the iPhone and iPad. And yes, that could be their end goal, but I can't help but wonder if maybe a desktop app store couldn't lead to more-open app stores across the board.

Limiting the app ecosystem makes sense for a phone. By it's very nature, its a limited device. It's OK if it can't do everything--as long as it lets me accomplish useful tasks while I'm on the run. On the other hand, users expect to get more work done on their iPads. Not surprisingly, the iOS SDK loosened up considerably with the iPad's release. Before, each application was kept entirely in its own sandbox. Now we can move files from one app to the next. It may not be complete access to the file system, but it has vastly improved the iPad's usefulness.

Soon we will have a full-blown desktop app store. Most of the excused given for limiting apps simply don't apply. We're no longer dealing with devices that have severely limited resources. We no longer need to worry about upsetting AT&T. Users don't need to jail break their computers to load applications from outside the app store. Most importantly, users will have even higher expectations on what applications can and should be able to do. This will create a considerable amount of pressure on Apple to open up the process, and despite what many people think, Apple is not immune to pressure.

In many ways, Apple is already on a slow path towards loosening restrictions on the iOS app store. They've lifted the ban on third-party languages. They've published a more specific list of their requirements. They continually add new features to the SDK that allow access to previously restricted features on iOS devices. I fully expect this trend will continue as Apple feels their way through what is obviously a tricky and difficult issue. I also expect this trend will accelerate once we have a desktop App store. It won't happen overnight, and it won't be perfect. But, I have a feeling that the Mac App Store will be a good thing for the larger App ecosystem.

Wednesday, October 13, 2010

Changing the transition animation for an UINavigationController

I love the UINavigationController class for iOS. It's a great framework for managing a wide range of view-swapping applications, and we get the transition between views for free.

But, what if we want to use a different type of transition animation? UINavigationController only has one option--the new view slides in from the right while the old view slides off the left. There's no direct mechanism, but it turns out that it's not too hard to manage, at least for a select set of transitions.

First, lets look at the UIView methods. The navigation controller has its own view, which will contain the subviews we wish to manage. in iOS 4.0 and later, we can use that view's block-based animation.

[UIView 
transitionWithView:self.navigationController.view
duration:1.0
options:UIViewAnimationOptionTransitionCurlDown
animations:^{
[self.navigationController
pushViewController:self.alternateView
animated:NO];
}
completion:NULL];


Note: when we actually call pushViewController: we are setting the animated value to NO. This disables the Navigation Controller's default animation. Instead, the block of code uses the defined transition (in this case UIViewAnimationOptionTransitionCurlDown).

The same thing can be done using iOS 2.0 or later (although, you cannot submit anything older than 2.0 at this time).

[UIView beginAnimations:@"transition" context:nil];
[UIView setAnimationDuration:1.0];

[UIView
setAnimationTransition:UIViewAnimationTransitionCurlDown
forView:self.navigationController.view
cache:NO];

[self.navigationController
pushViewController:self.alternateView animated:NO];

[UIView commitAnimations];


Also notice, the two methods use two slightly different constants to define the view type. However, they both support the same four options: curl up, curl down, flip left and flip right.

We can get a different set of transitions by setting a transition animation for the Navigation Controller's view's Core Animation Layer.


CATransition* transition = [CATransition animation];
transition.duration = 1.0;
transition.type = kCATransitionFade;
transition.subtype = kCATransitionFromTop;

[self.navigationController.view.layer
addAnimation:transition forKey:kCATransition];

[self.navigationController
pushViewController:self.alternateView animated:NO];


There's one big difference here. The other animations were local. They only affected the code within the block (or between the beginAnimations and commitAnimations calls). This is a global change, and will continue to affect the Navigation Controller's behavior until it is changed again (or cleared by setting the animation to nil).

This also has four options: fade in, move in, push or reveal. For all but the fade, you can also set the direction of motion (from the top, bottom, left or right--though the iPhone seems to reverse the top and bottom options). We've already seen the push animation--the default behavior is a push from the right. Move in simply slides the new view over the existing one. Reveal pulls the old view away, revealing the existing one. While fade simply cross-fades from one view to the next.

I really wish there was an easy way to do other animated transitions (for example, having a view appear to grow from the center of the screen, or shrink into the center of the screen). But, I suspect those would take a lot of work at the CALayer level. I made a few attempts using regular animation blocks and altering the size of the incoming view. I could get the size to animate, but the old view simply vanished, leaving my new view to appear over a white background. Not what I wanted at all.

Still, there's a lot of cool effects you could produce with just these options. Happy hacking!

-Rich-