Code, Code, Revolution!
iPhone apps come in all shapes and form. Some are really basic and doesn’t fill any other purpose than showing how much of a geek you are, others are just for laughs or passing time, some are really useful and practical. Personally I’m not much of geek app fan although you will find the Lightsaber app on my iPhone. Useful apps tend to have one thing in common: they depend on internet connections and communicate with a central server/back end. There are a few useful apps that don’t fall into this category, an example is the excellent FastContacts. From comments on this blog, emails and forums I get the impression that there are quite a few who struggle with their internet enabled apps. I want to share some ideas, tips and techniques that can simplify and improve your app.
I think the biggest problem for developers who want to build apps for the iPhone is the programming language itself. Before the iPhone I had never heard about Objective-C and that’s basically because Apple is the only major player who promote and use it. Even though Objective-C sits on top of C the syntax is not at all what I was used to and my C/C++ experience is more or less what we did at College. With the risk of being flamed I argue that no sane person build GUI applications in C/C++. The memory management is also quite different in Objective-C than C. If you are also new to Objective-C I would recommend that you pick up a book about it and read through the basics. Before I started developing I bought Cocoa Programming For MAC OS X by Aaron Hillegass, the first chapters do a great job of getting you up to speed on the basics of Objective-C.
Chances are you are more familiar with languages such as C#/VB.NET/Java/Ruby etc. To ease the implementation of your app you should try to put as much functionality as possible in your service. You can save a lot of grief by processing the data before it’s sent to your app, making sure you don’t have to cast types or parse complex structures in a language you are not totally comfortable with. There are more advantages with keeping the logic outside the application, your app will be faster because you don’t have to process the data further and it’s also easier make changes to your service than releasing a new app. An example: you want to display a price in your app, instead of sending the price as a float to the app, you format it and send it as a string. Changes to the currency format can then be done in the service.
Keep it small
If the data you want to consume come from a service you don’t control, build your own service that pull the data from that service and format it in a way that suite your app. Chances are you can reduce the information sent to the app so it includes exactly the bits you need. This will improve your applications performance.
Make as few connections/requests as possible
Depending on how much data you’re sending and receiving in your app you should optimize the requests and data per request. Receiving data in one request is always faster than making 2 or more requests for the same data. Receiving too much data at once can make your app feel slow initially. A good technique is to load data lazily, meaning when you actually need it. At the same time it’s a good technique to load what the user sees right now but also what you expect them to see next. A good example of this is an image gallery in a scroll view. Loading all the images at once will make your app slow, instead load the image the user is watching right now as well as the next and previous image. That way, when the user scroll to see the next image, it’s already loaded and the app feels really fast.
The easiest structured data format to consume is XML, of course. Apple has published a best practice app called XMLPerformance, it’s available at the iPhone developer portal. The fastest most effective way to parse XML is done using NSXMLParser, it is however a bit tedious to work with. I recommend that you design your XML structure to pass data as attributes when possible instead of elements. If you pass data inside elements you will have to read it through the foundCharacters event instead of accessing it directly in didStartElement. Here’s an example to explain this.
Bad XML structure
XML: <list><item>The item contains something interesting</item></list>
To parse this your will need a variable to hold text read from elements. This variable should be emptied/created in didStartElement. In foundCharacters you must append the read value to your variable. Finally in didEndElement you must assign the value of your temporary variable to the object where you want to store the consumed data.
Better XML structure
XML: <list><item info=”The item contains something interesting” /></list>
This requires less to parse. The didStartElement method takes a NSDictionary containing all attributes for that element so we can assign the value of info directly to our object by using the objectForKey method of the dictionary. I’ve implemented this technique in my CoreData example app.
While XML is an excellent markup for structured data it does provide quite a bit of overhead. If you’re passing lots of small pieces of information chances are the XML markup weighs more than the actual information. Try to keep your XML understandable but as short as possible by abbreviating element and attribute names.
There’s no reason to use SOAP when communicating with your service. The iPhone framework doesn’t support SOAP so don’t bother battling with it. There’s a common misconception that if you’re using .NET you have to use SOAP. This NOT true! By enabling HttpGet or HttpPost you can communicate with your ASMX service without SOAP and in .NET 3.5 WCF does support Get/Post as well. If you enable HttpGet you can call an ASMX web service like so: http://yourserver.com/service.asmx/FunctionName?parameter=somevalue.
The result will be plain problem free XML. .NET is an excellent back-end platform for your app, don’t believe the forum trolls.
Everyone loves images, right? Getting images from a server can be slow, especially if you’re on a slow GPRS connection. Make sure the images you send are optimized for your app. Images you consume are not larger than they need to be, don’t load 800×600 sized image.
Run compression tests on typical images that you display in you app. The screen is rather small and most times the image doesn’t have to be super detailed. Normally you can compress a jpeg to 40-50% and still find the image acceptable on the iPhone. This will reduce the size of your full quality image with more than 50%! Your application be faster and the end user will thank you, their cell carrier won’t.
If you have a large amount of images that change over time, perhaps users upload their own images. Consider adding resize and compression functionality on your server. There are libraries available, some for free, that can do the resize and quality reduction for you. If you’re using .NET WebSuperGoo has an excellent library called ImageGlue (not free), or you can find free libraries that use GDI+.
If you are consuming large images from other sources than your own you can still route them through your own server and let it resize their images for your app.
If you want super detailed high quality images a technique to improve the user experience is to first serve an image of very low quality, jpeg of 15% or so. It will load almost instantly. Then start downloading your high quality image and swap the low quality image when it’s done. This technique is used by Facebook in their gallery. On a slow connection the image first appear blurry and after a short while it is swapped to a crisp high quality image. Noone wants to watch a a loading screen for 10 seconds.
CoreData is new in iPhone OS 3.0, and it’s great! If you’re pulling lots of data from a server consider using CoreData to store it on the phone so you don’t have to go get it over and over. CoreData is so easy to use that except from the initial learning curve it won’t require a lot of code or add complexity. Another benefit with storing server data on the device is that it will be available even offline. Apple has a information on CoreData and you can check out my post (comes with example project) on CoreData.
Ads: Web site hosting , Server Colocation
With this blog I try to provide useful tips and solutions for programming .NET, Objective-C and more. My name is Björn Sållarp, and I love writing code.
FF
August 7th, 2009 at 9:21 am
Thanks for two great articles. Maybe you could combine them into one? For example create a server side application (java/.net) that returns xml and is read by the ihpone app and stored locally? When an updated/new city is created on the server, a new xml i created and read by the iphone.
Thanks again!
Björn Sållarp
August 7th, 2009 at 12:44 pm
Hey FF, thanks for your feedback!
I’ve thought about a sample application that use a .NET web service to read/add data. Perhaps a little later this year, I’m too busy at the moment with other projects.
Laurent
August 10th, 2009 at 3:45 pm
Thanks for this article, it’s really helpful. I’m trying to create an iPhone application consuming a .net web service. This iPhone app should retain data in a Sqlite database, and i’m also considering using Core Data. My question is : how would you handle authentication with the web server without using SOAP (GET is a bad idea in that case) ? I think it is secure enough to send the auth data in POST with a SSL certificate, but does the iPhone SDK support it ?
I have another question, more general : how did you learn Objective C with your .NET background ? Personnaly I’m really confused about the syntax… what were your most precious resources in your learning process ?
Thanks in advance for your answers
Ries
August 11th, 2009 at 3:52 am
Much easer on the iPhone is to use json rather then using XML.
There is a great Lin that can take a json string into NSDictionaries.
Ties
Björn Sållarp
August 11th, 2009 at 8:08 am
For those interested in using JSON here’s a good tutorial on that:
http://iphonedevelopertips.com/cocoa/json-framework-for-iphone-part-2.html
Björn Sållarp
August 11th, 2009 at 8:26 am
@Laurent
Which authentication scheme to use depend on how your users are stored and what kind of authentication you are currently using (if any). The iPhone does support SSL and posting data is not a problem, look at NSMutableRequest.
You could use Basic Authentication and pass the credentials directly in your request but unfotunately there SDK doesn’t support Base64 encoding.
Forms based authentiction is also possible as the SDK supports cookies aswell.
If you’re starting out fresh, ie. no existing users, you could create your own authentication aswell. If you’re only calling two webservice methods you could simply pass the credentials in every method call.
At first I was very confused with the syntax aswell. In fact, I still find it rather stupid/cumbersome. The poor intellisense support in Xcode doesn’t help either. It took a while for me to find out that the escape key brings up a list of methods for an object.
I read the first chapters oc the book: Cocoa Programming For MAC OS X by Aaron Hillegass, that really helped and after that it was just to keep going at it and reading the API reference. Install the API reference in Xcode so you can look up objects directly instead of searching google.
Good luck with your app! Use Core Data, it will simplify your implementation
Sam
November 5th, 2009 at 1:19 am
Great post, thanks very much for taking the time to write it.
I was wondering whether you could tell me anymore about what you said in the above reply (“Forms based authentiction is also possible as the SDK supports cookies aswell”) Do you have any examples of this. I would really like to use this approach but wouldn’t know where to start.
Thanks
Sam
ken wong
February 11th, 2010 at 5:18 am
Great post, look forward to your post for using .net to add/edit/get data, thanks