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

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 \\ 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

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 \\ 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 \\ tags: , , ,

Apr 01

An interesting quantum mechanics effect makes it possible for some lucky owners of the current generation iPhone to connect to high-speed 3G networks today.

Hubert Hochsztapler, a researcher at the institute for nano-technology at The Royal Institute of Technology in Sweden, discovered back in 2004 that old GSM cellphones could be used as 3G phones using the quantum tunneling phenomenon.

Would it work on the iPhone?

The iPhone was not tested by Hubert Hochsztapler and his colleagues, but our own lab reports today confirm that most current iPhones are already 3G capable. No new hardware is required.

The iPhone contains an accelerometer which measures minute movements of the iPhone. This turns out to be a great benefit to achieving the 3G capability. But due to interference from the accelerometer when it’s inactive, you first need to open an application on the iPhone that makes use of the accelerometer. The Safari browser is an excellent choice, since it will also allow you to visibly enjoy the effects of the faster data connection provided by 3G.

First turn the iPhone from portrait mode to landscape mode, back and forth a couple of times to ensure that the accelerometer is engaged and working. You should see the display change between portrait and landscape mode. Now start downloading a very large web page and simultaneously begin shaking the iPhone lightly along its y-axis. Think of the iPhone as the yoke of an aircraft. You want to avoid pitching and rolling the iPhone as you’re shaking it.

If you hit the right shaking-frequency (41 Hz seems to be optimal), the electrons in the iPhone will reach their tunnel state and the radio transmitter will “tunnel-up” and connect to the AT&T 3G network in your area (if one is available).

Impact on Apple’s stock price?

A Gartner analyst recently reported that Apple has already placed an order for 10 million units of the new 3G iPhone from their manufacturers in Asia. But when current iPhone owners discover that their iPhone already is 3G capable, they will not upgrade as Steve Jobs has decreed they should. This will effectively turn Apple’s 10M order into one big iBrickload of phones, says April F. Olson, an analyst covering the AAPL stock for Hochs Securities.

It doesn’t work with all firmwares

This technical trick has been confirmed to work only on non-jailbroken 1.1.4 firmware phones (also known as the 4.1 release in the U.S.).

Please report your success with your “new” 3G iPhone in the comments below.

written by Nick

Mar 31

Beta 2 of the iPhone SDK was launched last week and as advertised it now includes Interface Builder. Unfortunately somebody forgot to tell the documentation department at Apple about this. There is no documentation about Interface Builder related to the iPhone to be found anywhere. Zip. Nada. Nothing.

Of course there’s the general Introduction to Interface Builder User Guide, but does not deal with any of the specifics for building an iPhone interface.

Online forums are filled with messages from bewildered iPhone developers. Some brave bloggers have posted tutorials, which in many cases feel like putting a square peg into a round hole just to get the darn thing working.

I’ve found one tutorial that stands out from the crowd and actually makes sense from a Model-View-Controller (MVC) perspective. Check out Scott’s Reason #2: Interface Builder is buggy and has no documentation on his curiously named “I Hate the iPhone SDK” blog.

written by Nick \\ tags:

Mar 27

If you’re using a UIWebView to display rich text from a string of HTML (as I described yesterday) you can even include HTML links to external URLs.

However when the external web page is displayed it is done using the same scale as your local HTML page. Unless the two pages are about equal in size, the visual transition is less than pleasing.

You can use the scalesPageToFit property of UIWebView to fix this. See line 13:

- (void)loadView
{
  // Create a custom view hierarchy.
  CGRect appFrame = [[UIScreen mainScreen] applicationFrame];
  UIView *view = [[UIView alloc] initWithFrame:appFrame];
  view.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;
  self.view = view;
  [view release];

  CGRect webFrame = [[UIScreen mainScreen] applicationFrame];
  webView = [[UIWebView alloc] initWithFrame:webFrame];
  webView.backgroundColor = [UIColor whiteColor];
  webView.scalesPageToFit = YES;
  [self.view addSubview:webView];
}

But this causes another problem: your internal HTML page probably looks a lot smaller than you would like. To fix this we’ll use a trick that web app developers use to optimize web sites for the iPhone.

To the HTML code add a meta viewport tag:

<meta name="viewport" content="width=320"/>

The complete code looks like this:

NSString *html = @"<html><head><title>The Meaning of Life</title><meta name=\"viewport\" content=\"width=320\"/></head><body><p>...really is <b>42</b>!</p></body></html>";
[webView loadHTMLString:html baseURL:[NSURL URLWithString:@"http://www.hitchhiker.com/message"]];

written by Nick \\ tags: , ,

Mar 26

A UITextView is great for displaying multiple lines of simple text. But when you need something more fancy, like headlines or highlighting text, then you should look at UIWebView. It’s not just capable of displaying web pages from a URL, but you can also specify the HTML you want to display as a string.

Create a UIWebView in a controller:

- (void)loadView
{
  // Create a custom view hierarchy.
  CGRect appFrame = [[UIScreen mainScreen] applicationFrame];
  UIView *view = [[UIView alloc] initWithFrame:appFrame];
  view.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;
  self.view = view;
  [view release];

  CGRect webFrame = [[UIScreen mainScreen] applicationFrame];
  webView = [[UIWebView alloc] initWithFrame:webFrame];
  webView.backgroundColor = [UIColor whiteColor];
  [self.view addSubview:webView];
}

Then you can add your rich text to the view like this:

NSString *html = @"<html><head><title>The Meaning of Life</title></head><body><p>...really is <b>42</b>!</p></body></html>";
[webView loadHTMLString:html baseURL:[NSURL URLWithString:@"http://www.hitchhiker.com/message"]];

The documentation is not very clear on what the baseURL is used for in the context of HTML that is loaded from a string.

written by Nick \\ tags: ,

Mar 25

After yesterday’s elaborate tutorial on how to create a Preferences UI, accessing the preferences from your code is a snap.

NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
delayBeforeDialing = [userDefaults floatForKey:@"delayBeforeDialing"];

The key, “delayBeforeDialing” in this example, needs to match the Key value in Root.plist.

There are different accessor methods depending on the type of variable you want to retrieve.

  • arrayForKey
  • boolForKey
  • dataForKey
  • dictionaryForKey
  • floatForKey
  • integerForKey
  • objectForKey
  • stringArrayForKey
  • stringForKey

You don’t have to use a UI for your preferences. If you just want to conveniently store values associated with your application, that you can read back later, you can use the setter methods of NSUserDefaults.

[userDefaults setFloat:delayBeforeDialing forKey:@"delayBeforeDialing"];

Read back the values as above.

written by Nick \\ tags: