iPhone-App Development for Web Hackers
So here is my situation: I’ve been doing solely web development over the past two years and am still very busy working for a startup in Tokyo. The iPhone 3g just went out and I want to build a cool prototype that utilizes GPS. Over the past week I’ve spent a couple of hours here and there to make a little proof-of-concept application. I wasted some time running around in panic so hopefully this article will help to get you focussed.
Allright, this is what this prototype should be doing:- Being able to access location information.
- Show a map with a marker for the current location.
- Get relevant information about that current location and show that in an ‘info’ tab.
Safari is so Amazing
It seems that Safari on the iPhone can accommodate all user interface needs for a non-gaming application. Also, if you really want to do graphics stuff, there is some cool vector rendering CSS you can do.
Joe Hewitt wrote a little CSS/JavaScript pack called IUI. It makes your web applications in Safari look like native iPhone apps. Awesome!
If it was up to me, I would be coding everything in Safari. Server-side Rails, Ajax and accessing iPhone Hardware through Javascript – the wet dream of any Web Hacker. Unfortunately the latter is not (yet) possible, so we will have to build a hybrid web application.
iPhone Safari specific JavaScript capabilities:- Storing data locally through SQL
- Get the physical orientation of the device.
More in this video (Click on “iPhone SDK for Web Developers”)
The Magic
Bottom line is that we don’t want to waste time and keep on programming web. Since we want to access hardware information, we will have to get down and dirty with the iPhone SDK. Our goal: Render a Safari Component and push GPS information through JavaScript and AJAX to the web application.
Programming Cocoa
Note: I am very convinced that in order to learn any language, you should just jump in right away – don’t build useless example projects.
The Cocoa set of tools is called Cocoa Touch and provides all the UI and Data Access things you need. On the iPhone you program in Objective-C 2.0 whatever the fuck that might be :] Aahrgh, so I have been doing Ruby for the past two years and I have a vague memory of C++. Ah well, Objective-C is just another OO programming language, so it shouldn’t be that big a deal.
This video explains basic Objective-C syntax (forward to 3:00): http://developer.apple.com/iphone/index.action (Click on “iPhone Application Development – Getting Started”). It will explain a bit about Cocoa’s Model View Controller which might be useful.
Don’t waste your time on Hello World
When downloading HelloWorld and opening that in XCode (apple’s IDE) I got freaked out by the amount of code and files. Normally, when learning a new technology, I take examples and re-purpose them for my project. This will not work right away for Cocoa Touch.
Note: many coding screencasts use old versions of XCode or Interface Builder. Make sure your SDK is up to date and that the screencast you’re watching isn’t using older versions.
The catch is that you need to use a thing called Interface Builder to stitch together your Objective-C code with UI Components. So it’s better to watch a little screencast. This Screencast will show you how to add a couple of buttons and hook them up to a specific callback. The dude talks very slow so you can fast-forward every now and then.
After that this screencast will show you how to jack in the Magic UIWebView – our precious Safari. In this screencast they hook up two buttons (back and forward) to the UIWebView.
Our first Application
Assuming you have downloaded the iPhone SDK. Mac programming is mostly done using an IDE called ‘XCode’. It can be found in the /Developer directory of your Mac.
Let’s create a new Project in XCode, I am using the name ‘Reccoon’, but I will refer to it as ‘MyProject’:

Next, double-click on the Resources/MyProjectViewController.xib. This will open up the Interface Builder. Thereafter, cover the whole window with a safari UIWebView:

To access that ‘web view’ in the controller, we need to add a class attribute to the MyProjectViewController. This is called an ‘external outlet’:

Also, you need to add some code in your MyProjectViewController.h to utilize it as you can see in the next piece of code.
Hooking up CoreLocation
Now let’s get some code from the LocateMe example that can be found in the iPhone Dev center and add MyCLController.* and the CoreLocation Framework:

Set this code to your MyProjectViewController.h
1 2 3 |
@interface ReccoonViewController : UIViewController <MyCLControllerDelegate> { IBOutlet UIWebView *webView; } |
The LocateMe example’s MyCLController has all kinds of funky debug output. We only want the Latitude and Longitude, so let’s modify a bit.
In MyCLController.h:1 2 3 4 5 6 7 |
// This protocol is used to send the text for location // updates back to another view controller @protocol MyCLControllerDelegate <NSObject> @required -(void)updateLatitude: (NSString *)latitude andLongitude: (NSString *)longitude; -(void)newError:(NSString *)text; @end |
In MyCLController.m, replace the method: locationManager didUpdateToLocation fromLocation, with:
1 2 3 4 5 6 7 8 9 10 11 12 |
// Called when the location is updated - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation { [self.delegate updateLatitude: [NSString stringWithFormat:@"%lf", fabs(newLocation.coordinate.latitude)] andLongitude: [NSString stringWithFormat:@"%lf", fabs(newLocation.coordinate.longitude)]]; } |
Now implement the necessary callbacks. (this code belongs before the @end in the ReccoonViewController.m)
1 2 3 4 5 6 7 8 9 10 11 |
#pragma mark ---- delegate methods for the MyCLController class ---- -(void)updateLatitude:(NSString *)latitude andLongitude:(NSString *) longitude { [webView stringByEvaluatingJavaScriptFromString: [NSString stringWithFormat:@"update_position(%@, %@);", latitude, longitude]]; } -(void)newError:(NSString *)text { [self debug: [NSString stringWithFormat:@"error: %@", text]]; } |
As you might see in the updateLatitude function, a Javascript call is executed on the webView Safari browser. This means that you can do all your positioning and maps mashupping in Javascript:
1 2 3 |
function update_position(lat, lng) { /* We have escaped from Alcatraz! Now it's time for AJAX and JSON goodness :] */ } |
My Reccoon Prototype
For my own purposes, I’ve made a little RubyOnRails project (pretty much all HTML) that uses the Google Maps API and the Geonames Wikipedia Reverse-Geocoding Service. This utilizes the IUI toolkit:



Note: in these screenshots I am simulating the location to be in Amsterdam (while I am still in Tokyo). The iPhone Simulator’s default GPS coordinates are somewhere in the western Chinese badlands.
Conclusion
Perhaps Cocoa development isn’t as scary as it seems, after the useful-results feedback loop started (getting into the flow) I was really enjoying it. This little prototype is just an example on how to quickly get some results for a demonstration application. I can imagine that more and more Cocoa programming is necessary when the product/service starts to evolve.
I know this article is a sloppy quick write-up, but if you find it useful please leave a digg :] Also, please place a comment below if you have any problems or questions – I will address them by updating this entry.
36 Responses to “iPhone-App Development for Web Hackers”
Sorry, comments are closed for this article.


Nice guide ... you might have me inspired to try some things out myself. Already have some nice ideas in the works.
Cool! I thought of the exact same thing but using the User Agent of the browser. Injecting Javascript call is even more awesome. Could save web developers a but load of time.
Great write up Dominiek! Digging it as we speak.
Hey - nice writeup. Would you mind offering your Xcode Project as a download in here? :)
"This utilizes the IUI toolkit"
By that you mean that the only thing your view as is a UIWebView? Or did you just use it as a container for the map?
Nice tutorial! Do you mind posting your source (tar or zip)?
Thanks for sharing your impressions.
Hey guys, I will put up a nicely packaged version of the source soon. Gotta run now, so stay tuned!
Thank you, looking forward to see the source :)
Question on GPS .... say you have some map tiles loaded (cached)on the iphone. Can one do mapping with on GPS and no 3G/Wifi access?
I was thinking of doing some location when you are in the Mountains with no cell or wifi service. You should be able to access GPS? If the maps were preloaded I would imagine you could locate and display based upon GPS ONLY?
@jkirby For jailbroken phones, there is a third-party Installer.app program that caches Google Maps information. So it should be possible to build an application which could pre-cache map tiles ahead of time and use them with the 3G's built-in GPS, even with no other network access.
You just have to know where you're going ahead of time and cache all the tiles for the area at all the resolutions that you need. Save the appropriate lat/lon info for each tile, so that later you can reverse map your coords back to the correct tile and zoom level. It would be a bit of drudge work, programming-wise, but not terribly difficult, I don't think.
When the Google Maps API first came out, I tinkered with stuff like that briefly, and it wasn't too hard to deal with. And from what I've seen, they've made a lot of improvements to the API since then.
The "Programming Cocoa" Objective-C thought is exactly where I'm coming from as well. I'm looking for a way to create my whole app in Javascript/HTML/CSS and deploy it to the iPhone for offline access.
Did you deploy your hybrid app onto the iPhone itself or is it web hosted? I can't seem to find any docs on how to deploy javascript only apps onto the phone.
Also, me too on the packaged source request :-)
Thank you for the article, but please expand on this with a click-by-click howto and/or post the source.
When you say "To access that 'web view' in the controller, we need to add a class attribute to the MyProjectViewController."... Your screenshot shows that the attribute is added to the .h file but when I click the + symbole to add the attribute it says .xib
Any ideas?
@all
here is the source: http://dominiek.com/assets/2008/7/19/Reccoon.tar.gz (Reccoon is the name of one of my in-draft startups)
The project is loading the web app from a remote URL (in this case http://localhost:3000/ where the RubyOnRails server runs). I guess it's also possible to deploy the webapp locally, but might require some extra hacking (and is not really interesting for my use-case at the moment).
@Matt, not sure about the + button and all. But I'm sure that the webView 'external outlet' needs to be set in both the XIB (by using the Interface Builder) and in the .h file. This screencast has a good example: http://iphonedevcentral.org/tutorials.php?page=ViewTutorial&id=34&uid=59068116
Goodluck guys!
Dominiek,
Just letting you know that the MyCLController files are missing from your project.
Dave
@Dave
You can use the MyCLController.h/.m from the LocateMe example from Apple. Just make changes as noted above.
What would be nice is to complete the example with the server/html code used here
@Dougal - Thank you for the tip on caching maps. A more general question is does the Apple Store allow you to include update bundles for your application? In other words can you download application resources (e.g, cached maps) separate from the "core" application?
Great tutorial! I love this sample so much, GPS, Maps, IUI and send message to Javascript, Amazing.... by the way, I upgrade the IUI code for like iphone main page (icon style), Could I join your talent IUI members?
anyway, I must be said, Thank you! Thank you! Thank you!
Great tutorial, thanks! Currently building a similiar application... we're using this iphone-google-maps component: http://blog.gammal.org/2008/05/google-maps-view-for-iphone.html
as with the solution offered by this tutorial it is not possible to pan the map around.... at least, we couldn't get it to work. Did somebody else?
Cheers!
Thanks for the cool tips. I can get this to run - but he update_position javascript function is not working/running. Are others getting this to fly?
I've updated the location delegate from the LocateMe example and followed the above directions. It compiles and brings up my local app http://localhost:3000/location. Works in Saf and my iPhone, except, of course, not getting a call from the js function from app code.
I am confused about the last javascript block of code - I assume that goes server-side?
I agree with jkirby - it would be great to get the sample HTML/JS server-side code as well to fully test this!! Right now I get a blank white window since I obviously don't have anything running locally at port 3000.
I'm a bit slow, so bear with me: I'd really like to be able to make a JS call on the iPhone to get me the GPS lat/lng data within a web page. Is this what you are enabling/trying to enable?
@Matt, The JavaScript code indeed comes from server-side but runs of course in the browser. Will try to post some nicely packages Server-side code sometime.
@Chuck, Almost, it is in fact letting the Native Application call a JavaScript routine that gets the lat/lng. So it is only one direction.
Very nicely done. Frankly, it exceeds my skills, even after messing around with the code.
If I wanted to create a site that could call that Javascript function, using the example you created, what would I need to do? Just change the URL in the code?
Thanks for the reply. From what you've seen of the SDK, do you think there is a way to go the other way (having a JavaScript function from any web page call a native app that can return the GPS lat/lng)?
thanks in advance, Chuck
'Works in Saf and my iPhone, except, of course, not getting a call from the js function from app code.'
Same problem here, tried messing around a bit and changing the update_position call to an alert but no joy. Any ideas?
Thanks
'Works in Saf and my iPhone, except, of course, not getting a call from the js function from app code.'
Same problem here, tried messing around a bit and changing the update_position call to an alert but no joy. Any ideas?
Thanks
Got it up and running - owe you my gratitude.
Created an app that keeps location manager open, then posts lat/lon and time to a SQL database, that then updates a map on my website.
But it seems to update longitude far more frequently than latitude. Anyone else having this problem? Click username for link to generated map.
Very nice write up, will try this for sure. Added to my delicious :)
pbump!! I wanted to show you something you'll love!! check www.flixwagon.com very cool.
I just downloaded the latest release for the iPhone SDK. I am not able to find the CoreLocation Framework in that. Anyone's got any ideas ??
@Vidit:
Google is your friend...
/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS2.0.sdk/System/Library/Frameworks/
Hi Dominiek,
Any chance you can package up the server side code. I'm new to this and would like to see the whole picture.
Thanks,
Ronnie
Yeah I'm with Ronnie on this, it'd be great if someone could show the javascript part too, I'm having real trouble getting that bit sussed :(
Thanks
Dominiek,
Extremely informative piece.
Please feed us server side code!
Best,
nik
Ran across this and thought you folks would find it interesting.
http://phonegap.com/
http://groups.google.com/group/phonegap
http://iphonemicrosites.com/news/phonegap-converts-webapps-to-native-apps/
This looks awesome paul, hopefully I can have a look when I get back from work, Thanks!!!