Jul 10

The App Store has finally launched. It’s available in iTunes 7.7 and from 2.0 iPhones and iPod Touch devices. Out of the 552 applications that are available today, I managed to get 4 applications listed. That’s almost 1% mindshare; not bad. And I have 5 more apps waiting for Apple’s review.

These are all applications that I have developed for clients:

Lingolook - 3 language titles

written by Nick Dalton \\ tags:

Apr 16

Many of the built-in applications on the iPhone have this nice blue pattern background.

iPhone Standard Screen Background Color

It’s easy to get the same effect in your applications. Just set the background to the built-in color called groupTableViewBackgroundColor. (Note that the documentation erroneously refers to this color as groupTableBackgroundColor.)

UIView *view = [[UIView alloc] initWithFrame:[UIScreen mainScreen].applicationFrame];
view.backgroundColor = [UIColor groupTableViewBackgroundColor];

written by Nick Dalton \\ tags: ,

Apr 15

There is an iPhoneDevCamp in NYC this weekend. Looks like a good un-conference event, so if you’re in the area, check it out. Sponsored by Socialight who are doing interesting things on mobile phones, and are apparently busy working on an iPhone version.

written by Nick Dalton \\ tags: ,

Apr 11

This Device Has Expired

This week Apple displayed their control over all iPhone developers by bricking all iPhones and iPod Touch devices used for development. The installed firmware expired at 12:01 am on April 8th. Much, much later in the afternoon Apple released an updated firmware.

Exploring iPhone Graphics Part 1

Pete begins a new trail, this time about graphics. Great stuff as usual.

iPhone OS 2.0 has embedded YouTube support

More and more integration type features are added to Safari for the 2.0 release.

written by Nick Dalton

Apr 09

Say you want each customer to accept your Terms of Service, or some other legalese, before they can use your iPhone application.

Display the screen upon startup

The standard AppDelegate code generated by Xcode creates and displays your first application screen. Here’s a way that you can use the hidden property of UIView to display your new screen first without disrupting the flow of the rest of the application.

// Create window
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
[window setBackgroundColor:[UIColor whiteColor]];

// Set up main view navigation controller
MainMenuViewController *navController = [[MainMenuViewController alloc] init];

// Create a navigation controller using the new controller
navigationController = [[UINavigationController alloc] initWithRootViewController:navController];
navigationController.navigationBarStyle = UIBarStyleDefault;

[navController release];

// Create Terms of Service screen
tosController = [[TermsOfServiceViewController alloc] init];
[window addSubview:[tosController view]];
navigationController.view.hidden = YES;

// Add the navigation controller's view to the window
[window addSubview:[navigationController view]];
[window makeKeyAndVisible];

Most of this is boilerplate code, more or less generated by Xcode. What’s new starts at line 14. Instantiate the new TermsOfServiceViewController and add it to the view. Standard stuff. The important line is #17, which hides the navigationController.

Dismiss the new screen

Now that the Terms of Service screen is displayed and the Main Menu is hidden we need a way to dismiss the ToS screen and return to the normal application flow.

In your AppDelegate class create a new method:

- (void)termsOfServiceAccepted
{
	tosController.view.hidden = YES;
	navigationController.view.hidden = NO;
}

In the TermsOfServiceController you would have a button that the user has to tap:

UIButton *acceptButton = [[UIButton buttonWithType:UIButtonTypeRoundedRect] retain];
acceptButton.frame = CGRectMake(kLeftMargin,
						applicationFrame.size.height - kBottomMargin - kButtonHeight,
						applicationFrame.size.width - kLeftMargin - kRightMargin,
						kButtonHeight);
[acceptButton setTitle:NSLocalizedString(@"ButtonAcceptTermsOfService", @"") forStates:UIControlStateNormal];
[acceptButton addTarget:self action:@selector(termsOfServiceAccepted:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:acceptButton];

When the button is tapped, the selector is called which in turn calls the above method in the AppDelegate.

- (void)termsOfServiceAccepted:(id)sender
{
	id applicationDelegate = [[UIApplication sharedApplication] delegate];
	[applicationDelegate termsOfServiceAccepted];
}

Only show the screen once

With this code the ToS screen is displayed every time the application is started. That will quickly get annoying. So let’s add some code to only show it once by using a boolean stored in NSUserDefaults.

NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
if (![userDefaults boolForKey:TERMS_OF_USE_ACCEPTED]) {
	tosController = [[TermsOfServiceViewController alloc] init];
	[window addSubview:[tosController view]];
	navigationController.view.hidden = YES;
}

And in the termsOfServiceAccepted method set the boolean in NSUserDefaults.

- (void)termsOfServiceAccepted
{
	tosController.view.hidden = YES;
	navigationController.view.hidden = NO;

	// Store acceptance in UserDefaults
	NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
	[userDefaults setBool:YES forKey:TERMS_OF_USE_ACCEPTED];
}

Now the ToS screen is only shown until the user taps the accept button. Your customers will be happy, as will your lawyers.

written by Nick Dalton \\ tags: , ,

Apr 08

When you add a framework to your project in Xcode, make sure you use Path Type = “Relative to Current SDK”. There is no option for this when you add the framework. So after the framework has been added to your project, command-click on the framework and select Get Info.

Your paths should look something like this:
System/Library/Frameworks/AudioToolbox.framework

Why is this important?

When you start developing using both the iPhone simulator and an actual iPhone device you technically switch SDK based on your target. And it’s a real pain to have to adjust all the framework paths each time.

written by Nick Dalton

Apr 07

First you need to add your file to the Resources folder of your Xcode project. Then you can access the file like this (assuming the file is called MyFile.txt):

NSString *filePath = [[NSBundle mainBundle] pathForResource:@"MyFile" ofType:@"txt"];
NSData *myData = [NSData dataWithContentsOfFile:filePath];
if (myData) {
	// do something useful
}

Here’s a complete example reading a help text file into a UIWebView.

NSString *filePath = [[NSBundle mainBundle] pathForResource:@"HelpDoc" ofType:@"htm"];
NSData *htmlData = [NSData dataWithContentsOfFile:filePath];
if (htmlData) {
	[webView loadData:htmlData MIMEType:@"text/html" textEncodingName:@"UTF-8" baseURL:[NSURL URLWithString:@"http://iphoneincubator.com"]];
}

If you want to read the file into a string, which you can then display in a UITextView, for example, then do this:

NSString *filePath = [[NSBundle mainBundle] pathForResource:@"important" ofType:@"txt"];
if (filePath) {
	NSString *myText = [NSString stringWithContentsOfFile:filePath];
	if (myText) {
		textView.text= myText;
	}
}

written by Nick Dalton \\ tags: , , ,

Apr 04

Five good iPhone related blog posts from around the web this past week:

Five Factors Shifting the Future of Malware and Platform Security

RoughlyDrafted Magazine publishes great, in-depth articles. Next time you grumble about the iPhone code signing process, consider the alternative.

Exploring iPhone Audio Part 4

Pete continues his excellent iPhone SDK audio trail. Lots of source code. My favorite type of post.

Is it possible to create multiline UITableView text cells?

AppStoreDeveloper.com is a growing forum for SDK developers. Here’s one of the livelier threads from the past week.

iPhone Dev SDK - The source for iPhone and iPod Touch development!

That’s a promising title for a blog. I just discovered Chris’ blog this week. Definitely worth adding to your RSS reader.

Best of April Fool’s Day online

There were many iPhone related April Fools jokes this week. TUAW has a good roundup.

written by Nick Dalton

Apr 03

A UIWebView is great for displaying rich text; you just format your text as HTML. But how do you display images in a UIWebView?

Since the iPhone is almost always connected you could just use a regular image tag referencing an image on a server somewhere:

<img src="http://example.com/img/foo.png" />

But that is less than optimal. What you really want to do is reference an image on the iPhone. One way to do this is to embed the image in the HTML using the data: URI scheme. Here’s an example:

<img src="data:image/png;base64,
iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABGdBTUEAALGP
C/xhBQAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9YGARc5KB0XV+IA
AAAddEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIFRoZSBHSU1Q72QlbgAAAF1J
REFUGNO9zL0NglAAxPEfdLTs4BZM4DIO4C7OwQg2JoQ9LE1exdlYvBBeZ7jq
ch9//q1uH4TLzw4d6+ErXMMcXuHWxId3KOETnnXXV6MJpcq2MLaI97CER3N0
vr4MkhoXe0rZigAAAABJRU5ErkJggg==" alt="Red dot" />

Here’s a great tool for converting any small image to the base64 encoding required by data:image:
www.abluestar.com/utilities/encode_base64/index.php

Adding images this way will allow you to create great looking, self-contained help files and about us pages for your iPhone applications.

written by Nick Dalton \\ tags: , ,

Apr 02

In light of yesterday’s “announcements” and rumors about the 3G iPhone, it’s good to remind yourself that there will eventually be new iPhones with different properties and capabilities than the current generation.

Developing for the iPhone is great because it’s a single platform. If you have ever tried to adapt a J2ME application for dozens of different phones, you know how painful that is. But don’t take the “single platform” idea too far and assume things like screen size.

Always ask the device about it’s capabilities and dimensions. For example, [[UIScreen mainScreen] bounds] will give you the size of the screen your application can work with. Don’t hardcode 320 x 480 pixels. A good way to test your UI is to allow it to rotate between portrait and landscape mode. If the UI can handle that without breaking or looking distorted, it will probably adapt to other screen sizes as well.

Going back to the 3G example, how would you know if an iPhone is 3G connected to a 3G network? There is nothing specific to 3G in the current API. There is a kSCNetworkReachabilityFlagsIsWWAN flag in SCNetworkReachability which is defined as “EDGE, GPRS, or other cell connection”. That could include 3G. But since there is a significant speed difference between EDGE and 3G it would be nice if Apple added another flag specifically for 3G reachability.

Another possibility is the UIDevice class, and specifically it’s model property. Currently this contains “iPhone” or “iPod Touch”. An “iPhone 3G” model string would make it pretty clear that a phone is 3G capable. But that’s a pretty crude way of describing capabilities. And it puts the onus on each application to map device names to specific capabilities. When you think about all the different iPod models you realize that this will get out of hand pretty quickly.

What we really need is a new capabilities API or framework where an application can query the device for specific information such as screen size, RAM size, network capabilities, etc.

written by Nick Dalton \\ tags: , , ,