I'm an Irish iPhone developer, currently migrating my skills from the web to Apples most popular mobile computing device. Based in County Leitrim, Ireland and working from home as a freelance developer in PHP, Perl, and Objective-C.

Contact me at andy@luibh.ie.

Easy JSON Parsing for the iPhone/iPad

So you have access to a JSON stream through an RSS feed or a rest API and you want to use the information in objective-c. 

Easy. Just include the ‘json-framework’ files in your application, #import “JSON.h”, and then do:

SBJSON *jsonParser = [[SBJSON alloc] init];
NSDictionary *dictResult = [jsonParser objectWithString:theString error:nil];	

You can then move through the items in the dictionary object and use them in your app. Cool.

UITableView Selection Smoothing

If you use table views, and you need to smooth the transition a little bit when selecting a row and pushing a view controller, I’d recommend looking into ‘performSelector’. Its basically a timer which allows you to call a method after a certain short delay.

When using table views this gives the selected row enough time fully animate the selection, before moving onto the new view.

// our own method called from the performSelector
- (void)didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
	MarketViewController *market = [[MarketViewController alloc] 
		initWithNibName:@"MarketViewController" bundle:nil];		
	market.eventMarket = [self.eventMarkets objectAtIndex:indexPath.row-1];
	market.title = [[self.eventMarkets objectAtIndex:indexPath.row-1] marketName];
	[self.navigationController pushViewController:market animated:YES];		
	[market release];		
}

// delegate method for table
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
	[self performSelector:@selector(didSelectRowAtIndexPath:) withObject:indexPath 
		afterDelay:0.1f];
}

Something else I just realised is that my tableviews weren’t automatically deselecting the rows when I returned from the push view controller. The following code rectifies that nicely (and smoothly).

-(void)viewDidAppear:(BOOL)animated {
	[tableMarkets deselectRowAtIndexPath:[tableMarkets indexPathForSelectedRow] 
		animated:animated];	
}

UITableView with Asynchronous Image Downloads

It seems that a lot of applications Im working on these days require a table view which downloads images off the web. Doing this synchronously is very messy and only results in a very laggy application while scrolling, so I found a nice solution by markj of markj.net.

He’s created an AsyncImageView class which allows you to supply a URL, and have it download the image in the background. This works nicely for a table view, and makes for a tidy solution to the asynchronous image downloading problem.

The original blog post about it is here. A packaged up version of a sample application including the table view code which downloads a series of images dynamically is available on my site here.

Its saved me a bunch of work and thanks must go to MarkJ, Robert A and Wayne who put together the original Yellow Jacket code.

NSXMLParser Freezing ? Put it in a thread.

Running NSXMLParser can be surprisingly time consuming when actually run on the device, even if the test data you’ve been using in the simulator gets parsed quite quickly, and takes next to no time at all.

Unfortunately when you go to run it on the iPhone itself, it can take a couple of seconds or more to do something which took milliseconds on your dev machine. This results in a fairly bad user experience when they are browsing your app, and it hangs periodically while parsing the XML.

The answer ? To move the XML parsing into a thread of its own, and let the UI continue to be useable while the parsing carries on in the background, bothering no-one else.

- (void)viewDidLoad {

[NSThread detachNewThreadSelector:@selector(parseXML) toTarget:self withObject:nil];

}

- (void) parseXML {

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

// RUN PARSING CODE HERE

[pool release];

}

iPad Economics

marco:

Given:

  • iPhones and iPods Touch in use today: 50-60 million1.
  • iPhones sold in the first year (Q3-4, FY 2007): about 1.4 million2. For most of this time, the price started at $499, but nearly everyone bought the $599 model.
  • iPhones sold in the second year (FY 2008): about 11.6 million, over half from Q4. Most sales in FY 2008 were the better, cheaper iPhone 3G.

How many iPads do you think will sell in 2010?

This is important for app economics. Many developers want to know how many potential iPad customers will exist to determine how quickly (or even whether) our apps need to be iPad-ready and how we should allocate our resources relative to the iPhone editions.

iPhone sales have largely followed the price drops. I expect the same to apply to the iPad, with the added caveat that I think the overall userbase will be smaller in the beginning. As I said in the first article:

Nearly everyone can justify having a phone — the only question is which phone, and it’s easy for people to rationalize spending a bit more money for the really nice one. The same rationale applies to iPod Touch owners: they’re already buying a portable music player, and the iPod Touch is just the medium- to high-end choice.

The national economic problems seem not to be noticeably affecting sales of high-end tech gadgets, so I won’t factor them in directly.

I’ll take a wild guess and say that I expect about 3 million iPads to be sold this year3.

So how will that translate to app sales from iPad owners? For simplicity, I’ll assume that the value of your app to users is approximately the same on the iPad as on the iPhone.

If my three-million-iPads prediction is accurate, and the iPhone and iPod Touch keep growing at steady rates, by the end of 2010, I predict that about 3-4% of app sales will be to iPad owners.4

But there’s another dilemma: it looks like there will be significant pressure, both political and technical, for universal apps that run on both the iPad and the iPhone. Like multiple-iPhone owners, this only counts as one sale, since one purchase of the app will run on both devices. So for any apps that use a universal edition, their entire existing customer-base will result in zero new sales. (This effect may not matter in the long run. For most iPhone apps, new sales outpace existing-customer upgrades by a large margin.)

A significant portion of iPad owners will probably also own an iPhone or iPod Touch, and you could argue that they would have bought the app for the iPhone anyway.

So not every iPad owner who uses your app will have been the result of another sale.

Economically, there doesn’t seem to be a huge incentive to spend a lot on an iPad edition.

I think, overall, this is a good thing: it should dampen the gold-rush effect, leaving most iPad development to those who care strongly about it and want to do it well.

Running the numbers like this helps clarify my opinion a bit on the iPad App Store timing question: since the initial gold-rush period won’t be anywhere near the magnitude of the iPhone’s, it’s unlikely to hurt your app much in the store if you’re not there exactly on day one.

Meanwhile, if the iPhone is likely to represent at least 90% of your sales for 2010, it’s probably not a good idea to slack off much on the iPhone versions of your apps, even if the iPhone is no longer the focus of the tech press.5


  1. Apple has sold over 70 million, but I’m assuming that not every device sold is still in use. 

  2. Via this Wikipedia image

  3. Through Q1-FY2011 to include the 2010 holiday season. In case you want to claim-chowder me later when I’m way off, I’ll make yet another chowderable claim that my predictions will end up having been comically low, in which case much of this post will be irrelevant, overstated, and wrong. You can usually count on me for that. 

  4. My math is intentionally fuzzy and hand-wavy. 

  5. Normally, I dislike footnotes. But they made sense for this article. I’m sorry to anyone who is annoyed at them as I usually am. 

Creating UIColor Objects from Hex Values

If you come to the iPhone from a web background, or are simply more used to hex based colors it can be a bit of pain working out their RGB equivalent for use as a UIColor.

Fortunately though there is a rather simple work around in the form of a macro.

#define UIColorFromRGB(rgbValue) [UIColor \
    colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 \
    green:((float)((rgbValue & 0xFF00) >> 8))/255.0 \
    blue:((float)(rgbValue & 0xFF))/255.0 alpha:1.0]

Usage is also delightfully simple, and is implemented like this:

cell.textColor = UIColorFromRGB(0x333333);

Where the 333333 is your normal hex color value minus the #.

Detect Single Tap in UIScrollView

There are an increasing amount of occasions when I’d need, and like, to be able to tap the background of an application to hide a keyboard during editing. It just seems to make good UI sense to tap on the main background and hide the keyboard so you can see what you’ve typed properly.

The following article does just that, and explains how to create a new instance of the UIScrollView which checks for a single tap and passes the event into a class of your choice.

iPhoneDeveloperTips.com - Detect Single Tap in UIScrollView

Accessing the Phone from within an Application

For some reason I had a hard time finding decent code for actually opening the phone application when a phone number is tapped.

See through button over UILabel.This is what I managed to come up with attached to a see through (no background color) UIButton, which was placed over the UILabel phone number text.

// read phone number from current advert data
NSString* value = [[resultsEntries objectAtIndex:0] objectForKey: @"phone"];
NSCharacterSet* characterSet = [NSCharacterSet whitespaceAndNewlineCharacterSet];
value = [value stringByTrimmingCharactersInSet:characterSet];
NSString* telUrl = [NSString stringWithFormat:@"tel:%@",value];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:telUrl]];
I seem to remember previous applications prompting me if I wanted to call the number or not but it looks like that was a feature of pre version 3.0 of the OS, and the default is now to call launch the phone application immediately.

If I get some time I might try and include that with an alert box to confirm they want to call the number, just seems like a tidier way to do it.

Resizing Remotely Fetched Image

So I had the code sorted for loading images remotely, and storing them in arrays to be displayed later, and then also fetching them directly from a URL to be shown in a UIImage. However up until this point Ive not had to resize them based on the newly loaded image data.

After a few fruitless searches I came across the following code which seems to work very well (so far).

// fetch image data
NSString* imageURL = [NSString stringWithFormat: 
  @"http://theimageurl.com/?id=%@", [[resultsEntries objectAtIndex:0] 
  objectForKey: @"image_large"]];
NSData* imageData = [[NSData alloc]initWithContentsOfURL: 
  [NSURL URLWithString:imageURL]];	
UIImage* image = [[UIImage alloc] initWithData:imageData];
		
// resize image
CGSize newSize = CGSizeMake(100, 100);
UIGraphicsBeginImageContext( newSize );
[image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
		
//image is the original UIImage
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();		
		
imageHeight = image.size.height;
[imageMain setImage:newImage];
[imageData release];
[image release];