Showing posts with label Objective-C. Show all posts
Showing posts with label Objective-C. Show all posts

Tuesday, November 10, 2009

iPhone Programming Tools - What's in my toolbox?

Having developed in many programming languages, one finds one has picked up several tools along the way. Despite the relative immaturity of iPhone OS development, there's a lot of Objective-C and Cocoa developers out there and even the newly welcomed faithful have helped contribute a lot of different tools to the trade. Well I've decided to put down what's in my toolbox to help anybody who stumbles here looking for a tool to do something and also as a big thanks to the developers of these tools. (Always remember, a bad workman always blames his tools). This list is by no means definitive and I'll update it as I go along. Suggestions are welcome - to make this list more useful and also to make my life easier :)

X-Code & Interface Builder (IB)
The de-facto IDEs barely rate a mention because you can't do much useful development without them. Or so I thought until I found out that the 'first' iphone virus (ikee virus) was not developed using X-Code or IB. No! "It's good old C on a linux cross compile tool chain" as the developer reveals in an interview here. No expertise on the iPhone OS required either! On a serious note though, X-Code and IB are useful. I'd love to hear from non-X-Code developers.

Leaks Performance Measurement tool
This is part of the Development tools bundled with the iPhone SDK. It deserves a special mention as it is useful to profile you application during testing to ensure no memory leaks are present in your coding. Developers used to developing in programming languages where memory management and garbage collection is handled for you are prone to write code that contains many memory leaks. If only finding them was as easy as fixing them...

SQLite Admin is an GUI administration tool for SQLite - which is used as the portable database for iPhone applications. This tool is useful to view the schema of the SQLite database created by CoreData and pre-populate SQLite databases. It requires the Adobe Air runtime.

This is a utility to read the backups from an iPhone device. The backups are created using iTunes sync. This tool used in conjunction with the SQLite admin lets you get the SQLite backups from a device, not just the simulator - hence you can see not just your application's databases but those of other apps!

iPhone PNG normalization tools
When I need to access an image that has been used in a third-party or apple's applications, I usually rename the application's *.ipa file from the iTunes music folder to a zip file and unpack it. Then I show the contents of the "*.app" bundle. Inside this bundle are the resources used in the application. The png images are not in an easily readable format. I use the following two tools to normalize them:
  1. iPhonePNG. This is a pre-compiled objective-c project
  2. iPhone PNG Normalizer. This is a python script
Do not use this to infringe on the copyright of others.

3 Twenty is a static library that provides many useful UI components, such as image viewers and general utilities. It is based on the facebook iphone app which is one of the most downloaded facebook apps.

More tools to be added as discovered.

iPhone / Objective-C reading .csv files

I've been working on an iPhone application where I needed to save some data into the SQLite database via CoreData. The data I had was in a .csv file and I needed to preload this data on to the phone. I had two choices:
  1. Create an SQLite database by some programmatic means and import this as the store for CoreData.
  2. Read the .csv file and create NSManagedObject instances which can be saved to the context.
Option 1 seemed a little more daunting for me, so I chose the second option using NSUserDefaults to save a flag that I'd already read the .csv. I'm still investigating the first option and will report back if I'm successful. Anyway, here's a sample of the contents of the file:
  1. 31939,-37.838596,144.96726,1 - abcd
  2. 31752,-37.856249,144.979277,2 - efgh
  3. 31751,-37.854868,144.978053,3 - ijkl
  4. 31750,-37.856094,144.977565,4 mnop
  5. 31749,-37.855388,144.9753,4 qrst
So that's an excerpt of the .csv - four columns of integer, double, double and a string. Including your csv file in the resources folder of your XCode project. Ensure that the "Target" checkbox is checked (Its on the top of the right content pane when the .csv file has been selected). Next is the code to load this data:
  1. //
  2. // load the points from our local resource
  3. //
  4. NSString* filePath = [[NSBundle mainBundle] pathForResource:@"a_csv_file" ofType:@"csv"];
  5. NSString* fileContents = [NSString stringWithContentsOfFile:filePath];
  6. NSArray* pointStrings = [fileContents componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
  7. //NSMutableArray* points = [[NSMutableArray alloc] initWithCapacity:pointStrings.count];
  8. for(int idx = 0; idx < pointStrings.count; idx++)
  9. {
  10. // break the string down even further to the columns
  11. NSString* currentPointString = [pointStrings objectAtIndex:idx];
  12. NSArray* arr = [currentPointString componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@","]];
  13. NSNumber *colTwo = [[NSNumber alloc] initWithDouble: [[arr objectAtIndex:1] doubleValue]];
  14. NSNumber *colThree = [[NSNumber alloc] initWithDouble: [[arr objectAtIndex:2] doubleValue]];
  15. NSNumber *colOne = [[NSNumber alloc] initWithInt:[[arr objectAtIndex:0] intValue]];
  16. NSString *colFour = [[NSString alloc] initWithFormat:@"%@", [arr objectAtIndex:3]];
  17. //... we can now use these pointers to save to the CoreData database
  18. }
In line 06 of the code above, we've selected a newLineCharacterSet as the delimiter so that the file is split by lines. In line 14, we then use the comma character set to split the columns by comma. Et Voila! Finally, see the rather odd way of reading strings. Must be a simpler way...

Wednesday, November 4, 2009

iPhone NSTimer on separate loop

This is a quick post about the usage of NSTimer to create a multi-threaded experience within an iPhone application. It does NOT address "backgrounding" or other challenges with creating threads in the highly restricted iPhone OS runtime.

I encountered this problem when I was trying to recreate a stopwatch application similar to the "Stopwatch" tab in the "Clock" application. I had an NSTimer object firing every tenth of a second, updating the label displaying the duration by calling a method "updateLabels".

NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:(0.1) target:self selector:@selector(updateLabels) userInfo:nil repeats:YES];


This quickly demonstrated my naivete regarding how the iPhone OS environment handles its run sequence. What happened was when the user touched the phone, my timer was delayed hence there was a noticeable lag (not firing until the user stopped touching the screen) in updating the labels. As this was not happening on the apple supplied app, I hit the search trail and found out about the "NSRunLoop" in this post. This object controls the run sequence of events in the app lifecycle and it places user events ahead of scheduled threads. The correct way of running the timer was hence:

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

NSRunLoop *runLoop = [NSRunLoop currentRunLoop];

NSTimer* timer = [NSTimer scheduledTimerWithTimeInterval:(0.1) target:self selector:@selector(updateLabels) userInfo:nil repeats:YES];

[runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];

[pool release];