Sep 16

The iPad UI Element Guidelines section of the iPad’s Human Interface Guideline forbids displaying more than one popover element at a time. Like this:

DontDisplayTwoPopoversOnTheiPad.png

Since there’s no explicit support in UIKit for avoiding this, I thought I’d show one way to remain in compliance with the HIG.

In the app depicted above, the left popover is the standard list component (left side) of a split view controller. It is shown in portrait mode when you tap the Bookmarks button. The popover on the right is an alert sheet that appears when you tap the action button.

The left popover is retained in the property self.popoverController, per Apple’s split view controller template. For the right popover I store the action sheet in the actionButtonActionSheet attribute.

When the action button is tapped this code is called:

- (IBAction)actionButtonSelected:(id)sender {
  // Dismiss other popovers, if visible
  if ([self.popoverController isPopoverVisible]) {
    [self.popoverController dismissPopoverAnimated:YES];
  }
	
  actionButtonActionSheet = [[UIActionSheet alloc] initWithTitle:nil 
                                                        delegate:self 
                                               cancelButtonTitle:nil 
                                          destructiveButtonTitle:nil 
                                               otherButtonTitles:NSLocalizedString(@"button.add.bookmark", @""),
                                                                 NSLocalizedString(@"button.open.safari", @""),
                                                                 NSLocalizedString(@"button.mail.bookmark", @""),
                                                                 NSLocalizedString(@"button.share.facebook", @""),
                                                                 NSLocalizedString(@"button.share.twitter", @""), nil];
  [actionButtonActionSheet showFromBarButtonItem:sender animated:YES];
  [actionButtonActionSheet release];
}

The important part for this discussion is the first couple of lines that dismiss the other popover if it’s visible.

For the opposite case when the Bookmarks button is tapped, you need to override the willPresentViewController method:

- (void)splitViewController:(UISplitViewController *)svc popoverController:(UIPopoverController *)pc willPresentViewController:(UIViewController *)aViewController {
  // Dismiss other popovers, if visible
  if (actionButtonActionSheet.visible) {
    [actionButtonActionSheet dismissWithClickedButtonIndex:-1 animated:YES];
  }
}

If your app has more than two buttons that launch popovers, then you should extract the code that dismisses other popovers into one method that you can call from all button action methods.

written by Nick \\ tags: , , ,

Sep 15

A quick tip if you just upgraded to SDK 4.1 and are experiencing strange compilation errors with old projects.

The error may look something like this:

/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator4.1.sdk/System/Library/Frameworks/CoreGraphics.framework/Headers/CGPDFContext.h:60:23: error: expected function body after function declarator
   CFDataRef metadata) CG_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_0);
                       ^
In file included from /Users/ab/project/project_Prefix.pch:7:

I’ve seen other variations as well, but they seem to stem from the Prefix.pch file, which you probably have not changed in a long time, if at all.

The solution is to update the iOS Deployment Target in your build settings. With SDK 4.1 Apple has helpfully removed the ability to select 2.x as a deployment target.

SelectDeploymentTarget.png

Just select iOS 3.0 or higher from the list, and your mysterious compilation errors should magically disappear.

Note: If you’re using the LLVM compiler and get a similar compilation error and the above solution does not work, check out this Developer Forum thread for a different solution. (That is from the iOS 4.1 Beta Forum, so you need to accept the new iOS Developer Program License Agreement before you can view it.)

written by Nick \\ tags:

Sep 09

One of the most popular pages on this blog is App Store Rejection Reasons. Since Apple refused to tell us what the “real” rules for the App Store approval process were, I shared my experiences in the hope that other developers could avoid making the same mistakes. The page ends with call to Apple to release all the hidden rules. Today Apple finally listened. 🙂

Here are finally the App Store Review Guidelines. The language of the guidelines is surprisingly informal; definitely not a product of Apple’s legal department. This makes it all the more believable that this is the actual internal checklist that reviewers use.

Daring Fireball has a nice collection of extracts from the guidelines that are funny, frank or puzzling.

I hope that Apple will start referring to these guidelines in their rejection emails, instead of the more diffuse paragraphs of the Developer Program License Agreement. This would also force them to add to the list as soon as apps are rejected and there’s no matching guideline to point to.

Apple also instituted an App Review Board where you appeal any app rejections. Obviously this is not an independent third party board, so don’t set your hopes too high. But instituting a formal review board is a great move by Apple. Hopefully the result will be less randomness in the approvals and rejections.

In another good move today, Apple also updated the iOS Developer Program License Agreement. Many of the egregious paragraphs that were added this spring with the apparent intent to stifle competition, have been removed. Bravo!

Now let’s hope that the HIG rules will still keep most of the bad Flash apps at bay…

written by Nick \\ tags:

Sep 03

The more I think about the possibilities of iOS apps on the new Apple TV, the less likely I think it will be. The two main stumbling blocks are:

  1. The difficulty of translating a touch interface to a TV screen.
  2. The new Apple TV has no storage; it’s a streaming only device.

But all may not be lost. I think the new AirPlay could open some interesting opportunities. A game that you play on your iPhone is very personal because of the small screen. But if the content of the iPhone screen was streamed to your TV then your friends can follow the game too.

Expand this to games that can utilize multiple devices, like Scrabble, and you can imagine some really interesting game play.

Granted all these devices will quickly add up in cost way beyond a Wii. But for an iHousehold most of these devices are probably already owned, including a few retired iDevices.

Another interesting aspect of this setup is that you don’t have to carry a stack of DVDs over to your friend’s house, you probably already have your iPhone with you and it is ready to play.

What do you think? What kind of entertainment apps would you like to play this way on your TV?

written by Nick \\ tags:

Sep 01

The fantastic rumors finally faced reality today when Apple presented their new fall lineup of devices. Here are my thoughts as an iOS developer on today’s announcements.

Live Streaming

It was great to be able to watch a live stream of the event instead of having to refresh half a dozen browser windows from various live bloggers. Rumors claimed that this might be a load test of Apple’s new data center. In reality the stream was served by Akamai (Apple’s longtime CDN partner) as evident by the edgesuite.net URL.

New iPod Nano

A new touch screen that looks very much like iOS. Except according to an Apple spokesman backstage, it isn’t iOS. That’s too bad. This would be a fun little device to write apps for. We’ll keep our collective fingers crossed that Apple will allow iOS-like apps to run on this device in the future. In the meantime I’m sure the jailbreak community will take a closer look at what’s really under the hood and find a way to run code on it.

New iPod Touch

Nothing unexpected here. Slight disappointment that the main camera is rather poor. If you’re relying on the camera for things like bar code scanning, this could spell trouble. I wonder if this “downgrade” is due to cost, a physical space constraint or a reflection of Apple’s intended audience for this device?

iTunes Ping

Apple is not content on just having an iTunes presence on Facebook, they want to be the social network. With 160 million credit card carrying iTunes users, they definitely have a running start. I really liked how they emphasized the privacy controls in Ping; a nice jab at Facebook.

As a developer I want an API to integrate with Ping. I think one of the critical success factors of Facebook is that they have established themselves as the social platform. A more integrated social platform within the iTunes/iOS ecosystem could be very interesting. Which of course begs the question of how does Game Center fit into this? Since both Game Center and Ping use iTunes accounts as the user identifier, it seems possible to merge or integrate the two in some way in the future.

New Apple TV

Smaller and cheaper, but nothing revolutionary. I love how Steve Jobs sells the idea of removing something (storage in this case) as a great benefit.

John Gruber claims that the new Apple TV does run iOS. It may be splitting hairs, but in my mind iOS implies UIKit, which is heavily oriented towards a touch interface, which I did not see much of in the demo. We’ll keep hoping that there will eventually be 3rd party apps and an App Store for the Apple TV.

For my media center, I will probably stick with my Mac Mini with Plex for now.

iOS Updates

iOS 4.1 is being released next week. Since we’ve had beta versions for a while, that’s no surprise. iOS 4.2 is coming in November which will be the first 4.x update for the iPad. While November technically qualifies as “fall”, it would have been nice to get all the 4.x goodness a bit sooner.

Overall 3 major OS releases within the span of 6 months is just a relentless pace. I wonder when the iOS development team at Apple last had a vacation? The competition is not sitting idle either, it’s definitely a great game to watch unfold. A huge benefit that Apple and iOS enjoys is the ease with which customers can upgrade to the latest iOS version. This greatly simplifies the life for us developers in that we can to a large degree assume the the latest version as a deployment target.

AirPlay

I think the most interesting announcement was AirPlay. This is an improved version of AirTunes. Now you can share audio, video, and photos with meta data between iOS devices (running iOS 4.2) and compatible accessories. A cool demonstration of this was at the very end when Steve Jobs was watching a movie on an iPad and then shared the video stream with an Apple TV. It’s not a stretch to imagine that the screen of any iOS app could be shared this way. I wonder if this is what the rumors about iOS apps on the Apple TV (nee iTV) were really based on.

written by Nick \\ tags:

Jul 09

Apple made significant changes to the MPMoviePlayerController API:s in iOS 3.2. Before, all you had to do was to initialize the MPMoviePlayerController and call play. Now things are a bit more complicated because videos can be played on a portion of the screen (good for the iPad) and not just in full screen mode.

But if all you want is to play a video in full-screen mode on all versions of the OS, then here’s some code:

NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:introVideoFileName ofType:@""]];
MPMoviePlayerController *moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:url];

// Register to receive a notification when the movie has finished playing.
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(moviePlayBackDidFinish:)
                                             name:MPMoviePlayerPlaybackDidFinishNotification
                                           object:moviePlayer];

if ([moviePlayer respondsToSelector:@selector(setFullscreen:animated:)]) {
  // Use the new 3.2 style API
  moviePlayer.controlStyle = MPMovieControlStyleNone;
  moviePlayer.shouldAutoplay = YES;
  [self.view addSubview:moviePlayer.view];
  [moviePlayer setFullscreen:YES animated:YES];
} else {
  // Use the old 2.0 style API
  moviePlayer.movieControlMode = MPMovieControlModeHidden;
  [moviePlayer play];
}
- (void) moviePlayBackDidFinish:(NSNotification*)notification {
  MPMoviePlayerController *moviePlayer = [notification object];
  [[NSNotificationCenter defaultCenter] removeObserver:self 
                                                  name:MPMoviePlayerPlaybackDidFinishNotification 
                                                object:moviePlayer];

  // If the moviePlayer.view was added to the view, it needs to be removed
  if ([moviePlayer respondsToSelector:@selector(setFullscreen:animated:)]) {
    [moviePlayer.view removeFromSuperview];
  }

  [moviePlayer release];
}

 

Recently I’ve been doing some development using cocos2d and I had to make some small changes to the code. (If your app is in portrait mode, then you may not have to do the rotation transform shown below.)

NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:introVideoFileName ofType:@""]];
MPMoviePlayerController *moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:url];

// Register to receive a notification when the movie has finished playing.
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(moviePlayBackDidFinish:)
                                             name:MPMoviePlayerPlaybackDidFinishNotification
                                           object:moviePlayer];

if ([moviePlayer respondsToSelector:@selector(setFullscreen:animated:)]) {
  // Use the new 3.2 style API
  moviePlayer.controlStyle = MPMovieControlStyleNone;
  moviePlayer.shouldAutoplay = YES;
  // This does blows up in cocos2d, so we'll resize manually
  // [moviePlayer setFullscreen:YES animated:YES];
  [moviePlayer.view setTransform:CGAffineTransformMakeRotation((float)M_PI_2)];
  CGSize winSize = [[CCDirector sharedDirector] winSize];
  moviePlayer.view.frame = CGRectMake(0, 0, winSize.height, winSize.width);// width and height are swapped after rotation
  [[[CCDirector sharedDirector] openGLView] addSubview:moviePlayer.view];
} else {
  // Use the old 2.0 style API
  moviePlayer.movieControlMode = MPMovieControlModeHidden;
  [moviePlayer play];
}

written by Nick \\ tags: ,

Jul 07

I’ve updated the App Store Rejection Reasons page with a few new items related to the iPad UI.

written by Nick \\ tags:

Jun 29

Today Apple announced their new iOS 4 Readiness Checklist. As a trailing sentence, almost as an afterthought, was this: “In addition, the App Store will no longer support applications that target iOS 2.x.”

That last sentence can be interpreted in several ways:

  • You will no longer be able to upload apps to the App Store that target iOS 2.x.
  • The App Store will really not support 2.x apps anymore and all such apps will therefore be removed.

The interpretation could have a significant impact on existing apps for several of our clients, so I called Apple for a clarification.

The official word is that going forward you will not be able to upload new or update existing apps that target iOS 2.x. All existing apps in the App Store will remain for sale even if they target iOS 2.x.

That of course is the sensible path. Although a general cleanup of the App Store to get rid of old apps that have not been updated since the 2.x days, might not be a bad idea…

written by Nick

Jun 28

Top iPhone/iPad Developers Wanted

Self Promotion Comments Off on Top iPhone/iPad Developers Wanted

My company, Pervasent, develops complex, enterprise class iPhone/iPad software. If that’s what you do, then please keep reading.

Please take a moment and look at our portfolio on our web site. If you have developed similar applications, then we definitely want to talk to you.

At Pervasent we really enjoy our work, and are looking for people who think developing iPhone/iPad applications is fun. We can’t wait to get to work (well, most of the time). We have the pleasure of working with other passionate developers, both on our own projects, and for our top-tier clients. We have been developing applications for the platform since the day it became available for third parties, so other than working for Apple, you can’t work with a more experienced team of developers than you can at Pervasent.

We have two immediate openings for an onsite project in San Francisco to work on a top 10 iPad app. For other projects, we are open to candidates in other locations. Please note that we only hire individuals, not companies. If you work for a consulting or contracting company and you want to offer *your* services, that’s fine, but then we want to see *your* qualifications, not your company’s aggregated portfolio.

These are contract to hire, or long-term contracting positions. And of course you will get paid for your work; no internships or revenue share BS.

All the developers in our company have 10-15 years of large scale, enterprise software development experience. If you have a similar background that’s a definite plus, but not a requirement. But design patterns, object modeling and data modeling must be ingrained in your thinking. Be prepared to answer questions more complex than “explain the benefits of an MVC architecture.”

You should have completed at least a couple of iPhone apps, either as an individual or as a part of a team. Please point us to your best apps in the App Store and describe your development role in each of them.

Beauty and quality comes from within, so at some point we will need to do a code review of something that you have written (this can occur in person on your equipment; we don’t expect you to send us your crown jewels). If that scares you, then this would be a good point to stop reading.

Finally, and most importantly, please tell us why you’re passionate about developing iPhone/iPad apps.

Thank you for your time and attention. We look forward to hearing from you.

written by Nick \\ tags:

Jun 23

My iPhone 4 just arrived. Here are my initial thoughts.

Retina Display

The first thing you notice as soon as you turn on the iPhone 4 is the new display. It is absolutely gorgeous. Not only is the resolution so much higher, but the pixels are also much closer to the glass, which combined creates a stunning effect. Sometimes when you walk into an electronics store they have dummy versions of some gadgets which have a sticker on the front panel to show you what it would look like if you could turn it on. The iPhone 4 display looks like that with the image right at the surface and with the same resolution as print.

Any text rendered in your app will automagically be rendered in the higher resolution on the iPhone 4. But any graphics will be scaled up. The graphics don’t look nearly as bad as the 2x mode on the iPad, but you definitely notice the difference in sharpness. For example compare the icons of the built-in Apple apps with the surrounding icons that have not yet been optimized for the new display.

Speaking of icons: Here’s a nice overview of all the different icon sizes that you should be creating for your apps to take full advantage of the screen resolution of each device. There are more sizes on this list than you think…

Speed

Having upgraded from an old iPhone 3G as my daily device, the speed of the iPhone 4 seems blazing. Everything is faster including installing apps and backups. It’s very easy to get spoiled. But keep in mind that a majority of your customers don’t have the iPhone 4. My main development and testing device is still a first generation iPod Touch. And I’m not done with my performance tuning until it runs fast on that device.

Fast Task Switching

The world has demanded “multitasking” on the iPhone, and Apple’s marketing department has delivered. In all seriousness, the engineers have implemented a really good mechanism for quickly switching between apps. However, as a user I still find it confusing. This is mostly because apps behave inconsistently when you launch/resume.

To participate in fast task switching you need to recompile your code using the 4.0 SDK. WIthout recompiling, your app will behave just like it does today under iOS 3.x and earlier: the app fully exits and launches from scratch each time. (Yes, I know that old apps still show up in the task bar when you double-click the Home button. But that’s because the task bar is a list of recently launched apps, most of which are no longer resident in memory, and even fewer are actually running.)

But you shouldn’t stop with a simple recompile. The important, and difficult, part is to maintain and restore the application state. If your app happens to be still in memory when it’s relaunched, then the state of the app will be just like the user left it. This is what the user expects. But if your app has been terminated, perhaps because the OS needed to reclaim the memory, then it will be launched from scratch. In this case it’s your responsibility to completely restore the state. The user has no idea of what the OS is doing behind the scenes, so the behavior of your app should not vary between these two situations.

 

written by Nick \\ tags: