TwitterCounter for @bigclick_dean

dBlog.com.au

My Development Blog

If you are here I am guessing that you are interested in iPhone/iTouch development and are looking for a place to start. Due to Apple’s NDA on the iPhone SDK there really isn’t much information out there on getting started with iPhone development, by writing this tutorial I hope to give people the confidence to get started developing on the iPhone and also to help myself get my head around it.
Lets get started

1. Getting your development environment setup

You will need a copy of the iPhone SDK (available for free at http://developer.apple.com/iphone). Once you have downloaded the installer (it is pretty big, 1GB+) you will need to let it run and to install all the required components.

By default the installer doesn’t add any icons to anywhere so you will have to navigate to /Developer/Applications to find the tools that you will need, I suggest that you drag XCode and Interface Builder to your dock as you will be using them alot!

Fire up XCode to make sure that it launches OK, if so then you are ready to get into it!

2. Getting the TouchXML Libraries

As you cannot use the standard NSXML* libraries for iPhone development (they will work in the simulator but not when you try to deploy the app to the real hardware, I found out the hard way after working on an app for days!) we will be using the TouchXML library from TouchCode

You will need to check the latest code out from the TouchXML SVN Repository, if you dont know how to use SVN I have included the required commands below.

Launch a new Terminal window
Create a new folder called “ExtraLibraries” where you would like to keep your iPhone development libraries (I save mine in /Developer/ExtraLibraries/)

mkdir /Developer/ExtraLibraries

Change into the new folder

cd /Developer/ExtraLibraries

Run the SVN checkout code

svn checkout http://touchcode.googlecode.com/svn/trunk/ touchcode-read-only

You will see the filenames scrolling up the screen and it should only take around 30 seconds to grab all the required files.

Now you have the TouchXML libraries on your local machine ready to start creating your first iPhone app.

3. Setting up your New Project

Now its time to get into the hands on development, start up XCode if you haven’t already and click File > New Project and you will see the window below.

New Project Window

Double click on “Navigation-Based Application”, enter name your project “AdvancedBlogTutorial” and click Save.

You should see the following screen appear with all of your project files.

Initial Project Window

You can lay this screen out any way you wish but my favourite is to make the screen as large as possible and to drag the horizontal resizer all the way to the top to allow for the largest possible “code view” area as possible, like below.

My Development Layout

4. Including TouchXML in our project

As we are using TouchXML for our xml parsing, we will need to import the required files and also edit some of the project settings.

In the menu bar click Project > Edit Project Settings and a new window will appear with 4 tabs at the top (General, Build, Configurations and Comments). We are only interested in the “Build” tab at the moment, so go ahead and click the “Build” Tab and the following window will appear.

Default Project Settings Window

The settings that we are interested in are “Header Search Paths” and “Other Linker Flags”, you can easily find these by typing the beginning of the name into the “Quick Find” at the top right of the window.

You need to add “/usr/include/libxml2″ to the “Header Search Paths” and you need to add “-lxml2″ to the “Other Linker Flags”.

Once you have done this you can close the settings window and you will be back at your project window.

Now that the libxml2 libraries have been included you will need to import the TouchXML files to your project, to do this simply right click on the “Classes” folder in the left hand pane and click Add > Existing Files…

You will be presented with a finder window and you will need to navigate to the location that you checked the TouchXML files out to (in my case it was /Developer/ExtraLibraries/) and then keep going to the following path “touchcode-read-only/TouchXML/Common/Source/” and select all the files and click “Add”. You will be presented with the following screen:

Add files dialog

Leave everything as default and click “Add” .

You should now see the CXML* files in your left hand pane and they are now available for your application to use.

We are now finally setup and ready to get going.

5. Setting up our Variables, Outlets and Classes

As we used the “Navigation-Based Application” template, much of our layout and code structure has already been created for us. We could have started this from scratch but for simplicity sake it is much easy to use one of the default templates.

Open up the “RootViewController.h” file by expanding the “Classes” folder in the left hand pane and clicking once on “RootViewController.h”, you should see the contents of the right hand pane change to that of the file you selected.

By default you will see

//
//  RootViewController.h
//  AdvancedBlogTutorial
//
//  Created by dBlog on 15/09/08.
//  Copyright __MyCompanyName__ 2008. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface RootViewController : UITableViewController {

}

@end

Change the code to the following

#import <UIKit/UIKit.h>
#import "TouchXML.h"

@interface RootViewController : UITableViewController {
    // This is the outlet for the blog view, it will allow the data from the controller to be used in a view
    IBOutlet UITableView *blogTable;

    // blogEntries is used to store the data retrieved from the RSS feed before being added to the view
    NSMutableArray *blogEntries;

    // loadSwirlie will display a loading overlay while the data is downloaded from the RSS feed.
    UIActivityIndicatorView *loadSwirlie;
}
@end

The first line, “#import “TouchXML.h”", will import the TouchXML library for us to use in this Controller, it is very important because if we do not include it here we will not be able to access any of the TouchXML features.

The second line, “IBOutlet UITableView *blogTable;”, will allow our view to access data from the controller, this will be where we add the individual blog entries.

The third line, “NSMutableArray *blogEntries;”, creates a new Mutable Array called blogEntries that will be where we store the RSS feed items.

Finally the forth line “UIActivityIndicatorView *loadSwirlie;”, is a view that will overlay the default “Load Swirlie” while the RSS feed is being downloaded, this is especially helpful when accessing via EDGE or when trying to read large feeds.

Save the file.

6. Digging into the core code!

Now that we have the headers all setup and our TouchXML libraries included we are ready to start on the real workhorse of the application, the RSS reader!

Open up the “RootViewController.m” file the same way that you did in the previous step.

You will see alot more code in this file as when the project was created from the template it also created most of the basic code, we will be using some of the auto-generated code and also adding some of our own.

The first thing that we want to do is to make our RSS grabbing function, to do this just paste the following code below the “@implementation RootViewController” line.

// grabRSSFeed function that takes a string (blogAddress) as a parameter and
// fills the global blogEntries with the entries
-(void) grabRSSFeed:(NSString *)blogAddress {

    // Initialize the blogEntries MutableArray that we declared in the header
    blogEntries = [[NSMutableArray alloc] init];	

    // Convert the supplied URL string into a usable URL object
    NSURL *url = [NSURL URLWithString: blogAddress];

    // Create a new rssParser object based on the TouchXML "CXMLDocument" class, this is the
    // object that actually grabs and processes the RSS data
    CXMLDocument *rssParser = [[[CXMLDocument alloc] initWithContentsOfURL:url options:0 error:nil] autorelease];

    // Create a new Array object to be used with the looping of the results from the rssParser
    NSArray *resultNodes = NULL;

    // Set the resultNodes Array to contain an object for every instance of an  node in our RSS feed
    resultNodes = [rssParser nodesForXPath:@"//item" error:nil];

    // Loop through the resultNodes to access each items actual data
    for (CXMLElement *resultElement in resultNodes) {

        // Create a temporary MutableDictionary to store the items fields in, which will eventually end up in blogEntries
        NSMutableDictionary *blogItem = [[NSMutableDictionary alloc] init];

        // Create a counter variable as type "int"
        int counter;

        // Loop through the children of the current  node
        for(counter = 0; counter < [resultElement childCount]; counter++) {

            // Add each field to the blogItem Dictionary with the node name as key and node value as the value
            [blogItem setObject:[[resultElement childAtIndex:counter] stringValue] forKey:[[resultElement childAtIndex:counter] name]];
        }

        // Add the blogItem to the global blogEntries Array so that the view can access it.
        [blogEntries addObject:[blogItem copy]];
    }
}

Now I know that probably looks quite confusing but I have tried to add detailed commenting to allow you to follow what It does. Basically it sends a request to the address that you specify and pulls back the response into the rssParser object. Once this is done it loops through the <item< nodes and adds it, along with its children to the global blogEntries Array.

Now that we have a function that will request, read and process a RSS feed into an Array we have to actually call it from somewhere.

Enter “viewDidAppear”!

This function will already be in your file as the template would have created it, but it will be commented out. Remove the comment tags and edit the code to look like the following:

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    // Check if blogEntries has already been filled, if not
    // then send the request
    if([blogEntries count] == 0) {
        // Create the feed string, in this case I have used dBlog
        NSString *blogAddress = @"http://dblog.com.au/feed/";

        // Call the grabRSSFeed function with the above
        // string as a parameter
        [self grabRSSFeed:blogAddress];

        // Call the reloadData function on the blogTable, this
        // will cause it to refresh itself with our new data
        [blogTable reloadData];
    }
}

The above code simply checks to see if the item count in blogEntries is zero, if true then it will call the grabRSSFeed function with the supplied URL and then reload the Table Outlet with the new data. You can change the URL to any valid RSS feed and it will work.

We are getting extremely close to a working application now, just a couple more small changes and we are up and running!

Ones of these is the “numberOfRowsInSection” function, if you have a look in your file you will see it up near the top and it will be returning a static value of zero. What this means is, is that every time the table is reloaded it calls this function to see how many cells it needs to draw. Currently this will always return zero and therefore it will never actually draw anything :(

What you need to do is to make it so when this function is called it returns the count of items in the blogEntries Array, this is very easy to do. Just change the “return 0;” line to the following:

return [blogEntries count];

Now whenever this function is called it will return the correct number of entries, that was easy wasn’t it?

Our final code change will actually generate the cells for the table view, we are just doing a simple cell that shows the title text, but this can be anything including icons, fonts, styles, etc.

Find the “cellForRowAtIndexPath” function in your file, then inside that function find “// Set up the cell” and enter the following code under it.

int blogEntryIndex = [indexPath indexAtPosition: [indexPath length] -1];
[cell setText:[[blogEntries objectAtIndex: blogEntryIndex] objectForKey: @"title"]];

What the above code does is it grabs the index of the item that is being generated and then calls the setText function on the cell with the “title” value of the corresponding entry in blogEntries. You could easily change this to “link”, “pubDate” or any other child node of the node.

Guess what? Its now time to run your application!

7. Running the code for the first time

Make sure that everything is saved and then click Build > Build and Go (Run), you can also press Command + Enter to do the same thing.

You should see the iPhone simulator appear and your application will start up, you should see…nothing!

What? You mean I spent all that time for an application that doesn’t even do anything?

No, no, no, It does do everything that you told it to..BUT, we forgot to link the table display to the blogTable Outlet..doh!

8. Linking the Table in the View to the blogTable Outlet

Double click on the “RootViewController.xib” file in the resources folder in the left hand pane, the “Interface Builder” application will launch with your RootViewController interface in it. You should see something similar to the image below:
Interface Builder

Now in the Main window you will see three icons, the “File’s Owner”, “First Responser” and “Table View”. What we need to do is to Control click and drag from the “File’s Owner” to the “Table View” icons, you will see a blue bar appear as you drag and when you let go over the “Table View” icon a little grey window will appear, see below:

picture-11.png

You will need to select “blogTable” as that is the Outlet we created in our header file. Once you are done you can save the interface and click “Interface Builder”.

9. The Moment of Truth

If you try to Build and Run your application now you should get some results in the screen, for my blog it looked like the following:
Mine Worked!

10. Project Files

Here are the source files for this project: Download the project source files

11. What’s Next?

Well currently you can’t really do much with the application apart from read the headers, I intend to create a series of tutorials outlining how to actually read the rest of the feeds on your phone, how to add multiple feeds and even how to add some simple animation to spruce things up. I will also be taking a look at memory management too as this tutorial hasn’t looked into this at all.

This all depends on time and also on how well this first tutorial goes. But hopefully there will be many more to come.

I hope that you all have a better idea of how to work with the iPhone SDK and also how to get the TouchXML library up and running (it took me a fair while to get my head around it!).

If you have any questions or if you find any bugs please let me know!

Until next time, bye bye!

Popularity: 44% [?]

Comments

There are 71 comments for this post.

  1. Vivek Beniwal on September 16, 2008 5:46 pm

    Kudos!!!!

    The touchxml setup was really helpful.
    I was trying to make stubs for web service calls from iPhone and the NSXmlParser was a pain in arse.

    Thanks a lot.
    Vivek

  2. Manikandan on September 16, 2008 7:09 pm

    Hi Dean,

    nice one. keep up your work :)

    One small bug I found,

    // Create a temporary MutableDictionary to store the items fields in, which will eventually end up in blogEntries

    NSMutableDictionary *blogItem = [[NSMutableDictionary] init];

    Should be

    NSMutableDictionary *blogItem = [[NSMutableDictionary alloc] init];

    Thanks,
    Mani

  3. Dean on September 16, 2008 9:52 pm

    Thanks for the support guys!

    @Vivek: I did find it quite difficult to get the TouchXML library to work the way I wanted it to straight up, but after a bit of playing around it was much more efficient than using NSXMLParser and much more scalable. Glad that I could save you some time!

    @Mani: Thanks for that, I have changed the code in the samples. Don’t forget when using alloc that you have to release the object when you are done or it may cause memory problems.

    Keep checking for new articles as there are a few I have in the works.

  4. Gabe Jacobs on September 19, 2008 2:35 am

    I am trying to implement a powerful rss reader in my app, but I am having a tron of trouble. I am totally stumped. I have a ton of errors, but I really do not know what is wrong. Do you think you could possible post the project like the guys at TheAppleBlog did http://theappleblog.com/2008/08/04/tutorial-build-a-simple-rss-reader-for-iphone/

    Thanks,
    Gabe

  5. Vivek Beniwal on September 19, 2008 8:15 pm

    Hi Dean,

    Can you tell me how to turn off namespace support in touchxml.

    While parsing a snippet of SOAP response message. TouchXml throws namespace errors.This is because i am not giving the whole document for parsing to cut down memory footprint, just a snippet of .

    regards
    Vivek Beniwal

  6. Leandro on September 22, 2008 12:56 am

    Fantastic!

    Continue with that tutorials series..

    Thanks.

  7. Ian lim on September 22, 2008 7:03 am

    Hi, Dean,

    You’ve done a pretty good job.
    This is what i have been searching. Thanks for the effort.
    Really appreciate. Again, thank you very much.

  8. Dean on September 22, 2008 10:30 am

    Thanks everyone for your comments, much appreciated. I will continue this tutorial for sure!

    @Gabe Jacobs: I will post the source for the next part that will include SQLite and Multiple views.

  9. Niels van Renselaar on September 22, 2008 10:33 am

    Really great tutorial! I am new to the developer scene of software (former webdeveloper), and I like this step to step tutorial. Although you may outline some of the syntax more, that makes most minds dizzy.

  10. matthew roberts on September 27, 2008 5:16 am

    Bring on another tutorial!

  11. Steve Murch on September 27, 2008 5:32 am

    Really terrific article.

    Just one question — is it really true that the NSXMLParser (the Apple example) doesn’t work when deployed to an actual iPhone device?

    I am still awaiting my developer program certificate, so I can’t test it. As you note, NSXMLParser does appear to work fine in the simulator, if overly complex.

    Or did I read that wrong? Thanks for any clarification, and kudos again on a great article.

  12. Dean on September 27, 2008 10:09 am

    Hey Steve,

    I am pretty sure that the NSXMLParser libraries are included in the iPhone SDK but all of the supporting NSXML* libraries have been stripped (like NSXMLDocument, etc). This means that it becomes quite hard to process complex XML files and using the TouchXML libraries makes it much easier. For a simple RSS feed with a few nodes the NSXMLParser can be used.

    Hope this helped!

    -Dean

  13. Philip Roy on September 27, 2008 10:42 am

    Hi, this is what I was after and hope the next tutorial comes along soon!!

    One thing I couldn’t find was the part in point 6 that talked about “numberOfRowsInSelection”. I did find “numberOfRowsInSection”, so wondered if it was a typo?

    Cheers, Phil

  14. Dean on September 27, 2008 11:01 am

    Howdy Philip,

    Thanks for that, it was a typo…oops :-S

    Next tutorial will be coming soon! Keep your RSS readers turning over!

    -Dean

  15. Jonathan Kupferman on September 28, 2008 6:40 pm

    For anyone getting a “Error: syntax error before ‘AT_NAME’ token” error in AppDelegate.m like I did, all I needed to do to fix this was add a “@end” to RootViewController.h

    In step 5 above it says to copy in the provided code which is missing the @end and is likely the reason that it is missing.

  16. Dean on September 28, 2008 9:46 pm

    Thanks for spotting that Jonothan, I have added the missing @end to the code in step 5.

    -Dean

  17. Manish on September 29, 2008 7:52 am

    Tried implementing the same, even after making proper connection in Interface builder I am not able to get the list of RSS feeds in the iPhone simulator.

    On debugging found that I am not able to step into the method nodesForXPath:, debugger just skips this method there by not filling any thing in the resultNodes array.
    Don’t know why this is happening:(
    Can any one help me out of this.

  18. Jason Martin on September 29, 2008 11:15 pm

    I dunno about the rest of you, but I’m getting a ton of errors, mainly “touchcode-read-only/TouchXML/Common/Source/CXMLNode.h:32:25: error: libxml/tree.h: No such file or directory”, even though I’ve followed the steps in step 4.

  19. Jason Martin on September 29, 2008 11:18 pm

    Disregard the above comment. I’m dumb, that’s all. For some reason, XCode decided that it was going to show me the settings for “Release”, not “Active (Debug)”, so I was making the changes to the wrong one. >_<

  20. Dean on September 30, 2008 12:33 am

    Hey Everyone,
    I have just released the files for this tutorial and I am still working on part 2. You can download the files from the end of the tutorial.

    @Manish: Are you using the feed from my blog or did you change it to another URL? If so then try changing it back to my feed url and see how it goes, it may be a case of malformed RSS XML. If all else fails you can download the project files and give them a go.

    @Jason: Heh I have done that a fair few times as well, you can choose “All Configurations” from the “Configuration” dropdown box in the Edit Project Settings window to ensure that all configs get the correct settings.

    -Dean

  21. James White on October 2, 2008 3:51 am

    Very good tutorial, but how can I combine the UIWebView tutorial with the RSS tutorial?

  22. Jonathan on October 5, 2008 5:51 pm

    I don’t see how loadSwirlie get used in RootViewController.m file. Is there is something missing for it?

  23. Dean on October 8, 2008 9:36 pm

    Hey Guys,
    Part 2 is still under construction and should be up soon, it will show you how to use the loadSwirlie and also how to combine the UIWebView tutorial to make a full featured RSS reader.

    Stay tuned!

  24. Wunk on October 11, 2008 11:17 am

    Great tutorial, I’ve been trying to wrap my head around Xcode for a while now but it’s not easy when your coding skills are limited to Turbo pascal, Delphi on windows and bash scripting ;)

    Small note:
    I’ve been using your examples to try and parse other types of XML feeds, but Xcode starts to cry when there’s a empty XML entry (it actually made xcode crash twice for me)

    Keep up the great tutorials, I’m looking forward to part two of this one..

  25. evan on October 11, 2008 10:16 pm

    Great tutorial – really looking forward to part 2

  26. Podcaster on October 12, 2008 8:10 pm

    Great tutorial.

    Do you have any plans to also make an NSXMLParser example? All of the ones I looked at on the web have lot’s of memory leaks.

    Thanks.

  27. Mason on October 17, 2008 2:36 am

    I love how simple this implementation is for this, but I have some questions about adding some complexity to it. I have started to build an application that pulls down some XML data and what I need to do is parse that data.

    I am just overall confused how exactly the XML is being read in your implementation. Can you please offer more explanation as to how the XML gets parsed and maybe even show some examples?

    Keep up the great work too, this blog is one of the best resources I have found for coding on the iPhone! Thank you for everything!

  28. Mason on October 17, 2008 2:37 am

    Oh, as a side note, it might even be a good idea to make a reader for the comment stream of this post, I am not sure how complicated that would be, but would provide a solid example.

  29. brian on October 27, 2008 8:56 pm

    Excellent tutorial!!

    Anxiously awaiting v2. Still in the works?

    Thanks so much!!

  30. Dean on October 29, 2008 12:11 am

    Hey All,

    Sorry for the delay, I have been snowed under with work (Clients, who needs them?).

    I am hoping to have the part 2 up sometime next week providing I get a clear run the next few days.

    Dean

  31. Alex on December 1, 2008 1:35 am

    Greate work! it makes much easier for people who do not have any deep information about iPhone SDK

  32. Hong on December 9, 2008 6:41 am

    The tutorial works well for me. But when i come to getting rss include japanese it failed (i tried two, e.g. http://www.j-wave.co.jp/blog/index.rdf)…I traced down a bit and seems the libxml2 classes cannot parse xml element with jap characters, no node can be parsed…

    can anyone confirm it’s about the japanese characters and any methods to work this around? thanks…

  33. Abhang on December 9, 2008 12:24 pm

    Hi there,
    I stumbled upon your blog while building an RSS reader for myself. I have an issue with atom feeds though. Well my app works perfectly for RSS feeds but not for atom feeds. I understand this is some atom xpath issue. For eg your code would not parse this blog feed.

    http://feedproxy.google.com/guykawasaki/Gypm

    Any thoughts on that.

  34. Brennon on December 14, 2008 2:03 am

    Hi Dean,

    Ok, I’m having trouble getting theTouchXML into my project. I got it all into the Terminal, but I think I missed something when trying to actually put it into the project.

    Thanks!

  35. Alexander on December 21, 2008 2:37 am

    When is part 2 coming out?! I’m really eager to see it! Great tutorial!

  36. Matt on December 24, 2008 7:38 pm

    Has anyone had problems with TouchXML returning extra nodes that are not in the original XML?

    When I NSLog each top level node, it returns 7, instead of the 2 that are actually there. The XML is 100% valid…

  37. Matt on December 24, 2008 7:49 pm

    Solved my own problem if it helps anyone else… The problem was that my XML feed was formatted with indent spacing and new line characters. By removing those, and having the feed all one line, it worked perfectly.

  38. ioannis_gr on January 24, 2009 7:31 pm

    Thanks a lot. I’ll be waiting for the next…

  39. Hadley on February 3, 2009 10:11 pm

    Hi Steve

    The tutorial is great – Thanks!

    I’d like to try to build an RSS reader like this that can handle feeds that require HTTP authentication and SSL. Could you point me in the right direction? I’ve read arround a bit but am stuck.

    Cheers.

    Hadley.

  40. Schwartz on February 25, 2009 7:18 pm

    This is terrific. Thanks, Dean!

    I haven’t found a lot of documentation in general for the TouchXML / TouchCode classes. Is there anything you’d suggest reading that sits in complexity somewhere between this tutorial and just flipping through the libraries themselves?

  41. Jonathan Miller on February 28, 2009 6:14 pm

    Thanks so much for the tutorial. It was clear and concise, just what I needed as I am just beginning to develop for the iPhone!

  42. Schwartz on March 4, 2009 5:32 pm

    Forgive the newbie question, but why do you use XPath here rather than scanning the document with NSXMLParser? I’m just reading through the NSXML* documentation, and it gently directs towards event-driven parsing for reading simple data on a memory-constrained device. (And do you know if event-driven parsing available on the iPhone without using TouchXML?)

    I’m utterly, totally, depressingly and likely apparently unfamiliar with this stuff, so apologies if the question is dumb.

  43. Martijn on March 6, 2009 9:19 am

    Very nice tutorial!

    Works fine with your RSS url.
    I tried to use another RSS url with an .rss extension, but that did not work.
    Other urls without extension work great.
    Is it possible to handle urls with a .rss extension?

    Thanks in advance

  44. Tina on March 26, 2009 2:37 am

    Thanks for this tutorial… it very helpful to create a rss reader but i was wondering if you can help and tell me how to display the small summary of the feed under the title and add the date in as well. i will be very grateful if you can help me. cant seem to figure out the code to add this small summary and date.

    Many thanks

  45. Adam Oliver on April 5, 2009 2:45 am

    For the empty value issue, you can just check the value first and handle appropriately.

    if ([[resultElement childAtIndex:counter] stringValue] != nil) {
    // Continue normally
    } else {
    // Handle empty value
    }

  46. Dean on April 5, 2009 8:53 am

    Hey all,

    I have just posted another part to the RSS Reader Tutorial Series that goes into setting up a UITabBar and UINavigationBar. The next part is going to go into storing RSS feed URL’s in a SQLite Database and also how to create custom UITableView cells in code to have multiple lines of text and images.

    Please spread the word!

    Cheers,
    Dean

  47. raj on April 15, 2009 12:09 pm

    I have done the same thing given in this tutor and its giving 338 error and 52 warnings

  48. Bob on April 17, 2009 3:37 pm

    great tutorial! Thanks for writing these!
    I built the app per your instruction and it worked perfectly, but when trying to change feeds, (specifically to an RSS 1.0 feed) I get no nodes returned when the xPath query happens (@”//item”)
    This seems to be a difference from RSS 1.0 to 2.0 but I can’t find any info on xpath specifically for an RSS version..
    Any idea what query would need to be there instead of //item ?
    Thanks so much,
    Bob

  49. Jonathan Wight on April 18, 2009 11:50 pm

    Hey Dean,

    I’m the author of TouchXML and I must say – great job on the tutorial. I only wish I had known about it sooner so I could have pointed folks to it.

    I wonder, I’d love to adapt this as the official TouchXML tutorial and put it in the source code and/or on the Google site itself. Would you be interested?

  50. linki sponsorowane on April 23, 2009 8:17 am

    iPhone rulez! thx for all informations

  51. sas on April 23, 2009 9:14 am

    Um, I’m absolutely using NSXMLParser in an iPhone app, tested on the actual device. In which way does this fail for you?

    Sven

  52. Marcus Rodrigues on May 15, 2009 2:22 am

    So, it looks like the webaddress for the TouchXML library has changed, it only downloaded a READ ME file to my computer, wich says: All touchcode source has been moved to the mercurial SCM.

    See http://code.google.com/p/touchcode/source/browse/ for more details.

    Unfortunatelly, it seems I am to dumb to find the right URL for the new download, can anyone point me to the right place?
    Thx in advance!

  53. Harris on May 15, 2009 11:15 pm

    Here are a couple of updates needed on this page:

    Step 2
    That SVN doesn’t have the code anymore.
    You can download the code now from http://code.google.com/p/touchcode/downloads/list

    Step 4
    You need to Add some more existing files:
    /TouchXML/Externals/tidy/include
    /TouchXML/Externals/tidy/src

    Thanks so much for this useful page. Please make the above updates and it will be even more useful!

    Harris.

  54. sertorio on May 29, 2009 5:20 am

    That was a great tutorial, but i have a problem with adding attributes to my elements in code.. how do i add attributes to elements at run-time in touchXML?

    sertorio

  55. Aaron on July 4, 2009 11:21 am

    I am getting 32 errors and 13 warnings:

    Building target “AdvancedBlogTutorial” of project “AdvancedBlogTutorial” with configuration “Debug” — (32 errors, 13 warnings)
    cd /Users/aharontam/Documents/AdvancedBlogTutorial
    setenv PATH “/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin:/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin”
    /Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/gcc-4.2 -x objective-c -arch i386 -fmessage-length=0 -pipe -std=c99 -Wno-trigraphs -fpascal-strings -fasm-blocks -O0 -Wreturn-type -Wunused-variable -D__IPHONE_OS_VERSION_MIN_REQUIRED=30000 -isysroot /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator3.0.sdk -fvisibility=hidden -mmacosx-version-min=10.5 -gdwarf-2 -iquote /Users/aharontam/Documents/AdvancedBlogTutorial/build/AdvancedBlogTutorial.build/Debug-iphonesimulator/AdvancedBlogTutorial.build/AdvancedBlogTutorial-generated-files.hmap -I/Users/aharontam/Documents/AdvancedBlogTutorial/build/AdvancedBlogTutorial.build/Debug-iphonesimulator/AdvancedBlogTutorial.build/AdvancedBlogTutorial-own-target-headers.hmap -I/Users/aharontam/Documents/AdvancedBlogTutorial/build/AdvancedBlogTutorial.build/Debug-iphonesimulator/AdvancedBlogTutorial.build/AdvancedBlogTutorial-all-target-headers.hmap -iquote /Users/aharontam/Documents/AdvancedBlogTutorial/build/AdvancedBlogTutorial.build/Debug-iphonesimulator/AdvancedBlogTutorial.build/AdvancedBlogTutorial-project-headers.hmap -F/Users/aharontam/Documents/AdvancedBlogTutorial/build/Debug-iphonesimulator -I/Users/aharontam/Documents/AdvancedBlogTutorial/build/Debug-iphonesimulator/include -I/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator3.0.sdk/usr/include/libxml2 -I/Users/aharontam/Documents/AdvancedBlogTutorial/build/AdvancedBlogTutorial.build/Debug-iphonesimulator/AdvancedBlogTutorial.build/DerivedSources/i386 -I/Users/aharontam/Documents/AdvancedBlogTutorial/build/AdvancedBlogTutorial.build/Debug-iphonesimulator/AdvancedBlogTutorial.build/DerivedSources -include /var/folders/OF/OFeBZwdYHFq2aCVvIEtK-++++TI/-Caches-/com.apple.Xcode.501/SharedPrecompiledHeaders/AdvancedBlogTutorial_Prefix-gczukikiherrtparnzhmyitoouqf/AdvancedBlogTutorial_Prefix.pch -c /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m -o /Users/aharontam/Documents/AdvancedBlogTutorial/build/AdvancedBlogTutorial.build/Debug-iphonesimulator/AdvancedBlogTutorial.build/Objects-normal/i386/CTidy.o
    In file included from /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:30:
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.h:32:18: error: tidy.h: No such file or directory
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.h:33:20: error: buffio.h: No such file or directory
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m: In function ‘-[CTidy tidyData:inputFormat:outputFormat:diagnostics:error:]‘:
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:46: error: ‘TidyDoc’ undeclared (first use in this function)
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:46: error: (Each undeclared identifier is reported only once
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:46: error: for each function it appears in.)
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:46: error: expected ‘;’ before ‘theTidyDocument’
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:53: warning: implicit declaration of function ‘tidyOptSetBool’
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:53: error: ‘theTidyDocument’ undeclared (first use in this function)
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:53: error: ‘TidyXmlTags’ undeclared (first use in this function)
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:58: error: ‘TidyOptionId’ undeclared (first use in this function)
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:58: error: expected ‘;’ before ‘theOutputValue’
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:60: error: ‘theOutputValue’ undeclared (first use in this function)
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:60: error: ‘TidyHtmlOut’ undeclared (first use in this function)
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:62: error: ‘TidyXhtmlOut’ undeclared (first use in this function)
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:67: error: ‘TidyForceOutput’ undeclared (first use in this function)
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:70: warning: implicit declaration of function ‘tidySetOutCharEncoding’
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:74: error: ‘TidyBuffer’ undeclared (first use in this function)
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:74: error: expected ‘;’ before ‘theErrorBuffer’
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:75: warning: implicit declaration of function ‘tidyBufInit’
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:75: error: ‘theErrorBuffer’ undeclared (first use in this function)
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:76: warning: implicit declaration of function ‘tidySetErrorBuffer’
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:82: error: expected ‘;’ before ‘theInputBuffer’
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:83: warning: implicit declaration of function ‘tidyBufAlloc’
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:83: error: ‘theInputBuffer’ undeclared (first use in this function)
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:88: warning: implicit declaration of function ‘tidyParseBuffer’
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:102: warning: implicit declaration of function ‘tidyBufFree’
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:105: warning: implicit declaration of function ‘tidyCleanAndRepair’
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:114: error: expected ‘;’ before ‘theOutputBuffer’
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:115: error: ‘theOutputBuffer’ undeclared (first use in this function)
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:116: warning: implicit declaration of function ‘tidySaveBuffer’
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:133: warning: implicit declaration of function ‘tidyRelease’
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m: In function ‘-[CTidy tidyString:inputFormat:outputFormat:diagnostics:error:]‘:
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:140: error: ‘TidyDoc’ undeclared (first use in this function)
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:140: error: expected ‘;’ before ‘theTidyDocument’
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:147: error: ‘theTidyDocument’ undeclared (first use in this function)
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:147: error: ‘TidyXmlTags’ undeclared (first use in this function)
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:152: error: ‘TidyOptionId’ undeclared (first use in this function)
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:152: error: expected ‘;’ before ‘theOutputValue’
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:154: error: ‘theOutputValue’ undeclared (first use in this function)
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:154: error: ‘TidyHtmlOut’ undeclared (first use in this function)
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:156: error: ‘TidyXhtmlOut’ undeclared (first use in this function)
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:161: error: ‘TidyForceOutput’ undeclared (first use in this function)
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:164: warning: implicit declaration of function ‘tidySetCharEncoding’
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:168: error: ‘TidyBuffer’ undeclared (first use in this function)
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:168: error: expected ‘;’ before ‘theErrorBuffer’
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:169: error: ‘theErrorBuffer’ undeclared (first use in this function)
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:176: warning: implicit declaration of function ‘tidyParseString’
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:202: warning: implicit declaration of function ‘tidySaveString’
    {standard input}:60:non-relocatable subtraction expression, “L_OBJC_SELECTOR_REFERENCES_2″ minus “L00000000001$pb”
    {standard input}:60:symbol: “L_OBJC_SELECTOR_REFERENCES_2″ can’t be undefined in a subtraction expression
    {standard input}:54:non-relocatable subtraction expression, “L_OBJC_SELECTOR_REFERENCES_1″ minus “L00000000001$pb”
    {standard input}:54:symbol: “L_OBJC_SELECTOR_REFERENCES_1″ can’t be undefined in a subtraction expression
    {standard input}:48:non-relocatable subtraction expression, “L_OBJC_SELECTOR_REFERENCES_0″ minus “L00000000001$pb”
    {standard input}:48:symbol: “L_OBJC_SELECTOR_REFERENCES_0″ can’t be undefined in a subtraction expression
    {standard input}:unknown:Undefined local symbol L_OBJC_SELECTOR_REFERENCES_0
    {standard input}:unknown:Undefined local symbol L_OBJC_SELECTOR_REFERENCES_1
    {standard input}:unknown:Undefined local symbol L_OBJC_SELECTOR_REFERENCES_2
    In file included from /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:30:
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.h:32:18: error: tidy.h: No such file or directory
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.h:33:20: error: buffio.h: No such file or directory
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:46: error: ‘TidyDoc’ undeclared (first use in this function)
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:46: error: expected ‘;’ before ‘theTidyDocument’
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:53: warning: implicit declaration of function ‘tidyOptSetBool’
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:53: error: ‘theTidyDocument’ undeclared (first use in this function)
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:53: error: ‘TidyXmlTags’ undeclared (first use in this function)
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:58: error: ‘TidyOptionId’ undeclared (first use in this function)
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:58: error: expected ‘;’ before ‘theOutputValue’
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:60: error: ‘theOutputValue’ undeclared (first use in this function)
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:60: error: ‘TidyHtmlOut’ undeclared (first use in this function)
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:62: error: ‘TidyXhtmlOut’ undeclared (first use in this function)
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:67: error: ‘TidyForceOutput’ undeclared (first use in this function)
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:70: warning: implicit declaration of function ‘tidySetOutCharEncoding’
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:74: error: ‘TidyBuffer’ undeclared (first use in this function)
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:74: error: expected ‘;’ before ‘theErrorBuffer’
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:75: warning: implicit declaration of function ‘tidyBufInit’
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:75: error: ‘theErrorBuffer’ undeclared (first use in this function)
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:76: warning: implicit declaration of function ‘tidySetErrorBuffer’
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:82: error: expected ‘;’ before ‘theInputBuffer’
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:83: warning: implicit declaration of function ‘tidyBufAlloc’
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:83: error: ‘theInputBuffer’ undeclared (first use in this function)
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:88: warning: implicit declaration of function ‘tidyParseBuffer’
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:102: warning: implicit declaration of function ‘tidyBufFree’
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:105: warning: implicit declaration of function ‘tidyCleanAndRepair’
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:114: error: expected ‘;’ before ‘theOutputBuffer’
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:115: error: ‘theOutputBuffer’ undeclared (first use in this function)
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:116: warning: implicit declaration of function ‘tidySaveBuffer’
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:133: warning: implicit declaration of function ‘tidyRelease’
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:140: error: ‘TidyDoc’ undeclared (first use in this function)
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:140: error: expected ‘;’ before ‘theTidyDocument’
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:147: error: ‘theTidyDocument’ undeclared (first use in this function)
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:147: error: ‘TidyXmlTags’ undeclared (first use in this function)
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:152: error: ‘TidyOptionId’ undeclared (first use in this function)
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:152: error: expected ‘;’ before ‘theOutputValue’
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:154: error: ‘theOutputValue’ undeclared (first use in this function)
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:154: error: ‘TidyHtmlOut’ undeclared (first use in this function)
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:156: error: ‘TidyXhtmlOut’ undeclared (first use in this function)
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:161: error: ‘TidyForceOutput’ undeclared (first use in this function)
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:164: warning: implicit declaration of function ‘tidySetCharEncoding’
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:168: error: ‘TidyBuffer’ undeclared (first use in this function)
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:168: error: expected ‘;’ before ‘theErrorBuffer’
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:169: error: ‘theErrorBuffer’ undeclared (first use in this function)
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:176: warning: implicit declaration of function ‘tidyParseString’
    /Developer/ExtraLibraries/TouchXML/Common/Source/Tidy/CTidy.m:202: warning: implicit declaration of function ‘tidySaveString’
    Build failed (32 errors, 13 warnings)

  56. Aaron on July 4, 2009 11:56 am

    Never mind errors;
    I resolved it as Harris suggested;
    1. I unzipped TouchXML_1.0.6_Release.tar.bz2
    2. I found tidy folder under Externals
    3. In the project, I imported Externals/tidy/include and External/tidy/src

    And it worked.

    Thanks
    Aaron

  57. gazmac on July 8, 2009 4:20 pm

    Excellent tutorial and I’ve got it working using your url but can’t get it to load a blogspot feed. I read somewhere that this is fixable by adding a precompile file – something to do with Google’s freebie blog system using a different library. Anyone got any ideas or could point me in the direction of a solution?

  58. bart on July 23, 2009 11:52 am

    When using this piece of code I get the following exception :

    Entity: line 66: parser error : Input is not proper UTF-8, indicate encoding !
    Bytes: 0xA0 0×20 0×36 0×30
    nds.gif” width=”16″ height=”16″/>&nbsp;2200.0 euro<br/>Honda shadow

    How can I fix this using proper utf8 encoding ?

    thanks !

  59. Matthijn on July 23, 2009 5:25 pm

    @Harris, Thanks, Just what I needed, I got a load of errors too, and adding those files helped me out.

  60. Matthijn on July 23, 2009 10:30 pm

    Another thing I found, when you have an xml file with something lik this:

    aName

    (The part which is valid xml) it would crash.

    At this line:

    [blogItem setObject:[[resultElement childAtIndex:counter] stringValue] forKey:[[resultElement childAtIndex:counter] name]];

    (Allmost at the bottom) add this just one line above, and you should be fine.

    if([[resultElement childAtIndex:counter] stringValue] != NULL)

  61. anonymous on July 25, 2009 2:40 pm

    Hi there,

    Is there any solution to add all of the attributes (if any) from as well the main node (in this case “item”) as well from it’s childs to the array.
    Currently I use this:
    [bookItem setObject:[[resultElement attributeForName:@"id"] stringValue] forKey:[[resultElement attributeForName:@"id"] name]];
    To add the ID attribute from “item” to my array, but i have to do this for each of my attributes.
    So there are 2 problems left for me:
    -How do I do this automatic
    -How can I get attributes for child nodes?

  62. Tom on July 29, 2009 11:46 pm

    Fantastic tutorial,

    I’m still new to programming iphones but this is a great help.

    Thanks.

  63. Seree on July 30, 2009 4:17 pm

    orry for a newbie question but how can I read the “content:encoded” element?

    Generally, I use this with success on reading “description”, “title” but can’t use by specify “content:encoded”.

    objectAtIndex: feedEntryIndex? objectForKey: @”title”]

    Thank you in advanced.

  64. JordanC on September 6, 2009 5:58 am

    Hey Seree,

    For content:encoded you just need to use “encoded”. Because that’s the true name of the tag.

    Hope this helps.

  65. marko on September 15, 2009 1:21 pm

    31 warnings, 303 errors! even with Harris’ help!

  66. Malleswari on September 16, 2009 2:50 pm

    Hi,

    Really great tutorial. But I’ve got one problem i.e. if the XML node is like
    music , then the code is reading the xml node name as category instead of . Could any one of you suggest the solution for this??

    Thanks,
    Malleswari.

Trackbacks

  1. How to build iPhone Apps. Top Mobile Phone Twitter Apps for Social Media. | Tips on Enterprise 2.0 with Web 2.0
  2. 16 Resources for developing apps for the iPhone | blarnee.com
  3. Apple iPhone development links | 72dpi.net.au
  4. 200ml » 100 Free courses for iPhone Dev
  5. Tomato Factory » Blog Archive » Developer’s Corner #1
  • There are no trackbacks for this post

Write a Comment