If you want a more flexible and modern code have a look at the more recent version, which you can find here: http://www.touch-code-magazine.com/tutorial-building-advanced-rss-reader-with-ios6/
After getting the basic functionality up, let’s have a look how to refine the UI. The user experience is really important – in the end that’s what is going to make a user choose in between two applications with pretty much the same functionality.
Let’s the give the table view a nice header where we will also show the feed’s title. For the header I created this image (you will find it inside the demo application archive):
The table view provides the developer the possibility to set table header. We will create a custom class (a subclass of UIImageView) which will give you space to do further customization at will. Create a new class called TableHeaderView (choose you want it to subclass UIView in the new file dialogue)
We need the table header to show an image for the header background and provides means to set up the header text; thus make the new class to actually subclass UIImageView. You will need also a custom init method and a method to set the title text. Have a look at the interface file and update your source accordingly:
@interface TableHeaderView : UIImageView { UILabel* label; } - (id)initWithText:(NSString*)text; - (void)setText:(NSString*)text; @end |
We will have a custom init method just for sake of showing also how to do that. Let’s have a look at the very simple implementation file:
- (id)initWithText:(NSString*)text { UIImage* img = [UIImage imageNamed:@"arss_header.png"]; if ((self = [super initWithImage:img])) { // Initialization code label = [[UILabel alloc] initWithFrame:CGRectMake(20,10,200,70)]; label.textColor = [UIColor whiteColor]; label.shadowColor = [UIColor grayColor]; label.shadowOffset = CGSizeMake(1, 1); label.backgroundColor = [UIColor clearColor]; label.font = [UIFont systemFontOfSize:20]; label.text = text; label.numberOfLines = 2; [self addSubview:label]; [label release]; } return self; } - (void)setText:(NSString*)text { label.text = text; } |
That’s all we need from the table header class, so just head back to the RootViewController and update the source accordingly :
Initialize the table header inside viewDidLoad :
self.tableView.tableHeaderView = [[TableHeaderView alloc] initWithText:@"fetching rss feed"]; |
And update the header text when the RSSLoader fetches the RSS inside the updatedFeedTitle:
[(TableHeaderView*)self.tableView.tableHeaderView setText:rssTitle]; |
OK! Let’s fire up the application again and have a look if this time it looks nicer:
Yes, the table looks nicer, the subtle gradient looks great and the big RSS icon already gives the user a clear impression what the app is all about.
Let’s continue with the full preview of the articles. We are going to make use of the link attribute of the RSS items and in the DetailsViewController we will load up the link URL in a UIWebView. First double click on DetailsViewController.xib in XCode and arrange the view as show below – UIWebView taking all the space at the back and an UIActivityIndicator on the front centered in the screen. Make the UIActivityIndicator hidden, you will show it when the loading of the web page starts and hide it again when loading is finished.
Update the interface of DetailsViewController so that it conforms to UIWebViewDelegate protocol and lay down the outlets for the UI:
@interface DetailsViewController : UIViewController <UIWebViewDelegate> { NSDictionary* item; IBOutlet UIWebView* webView; IBOutlet UIActivityIndicatorView* loader; } @property (retain, nonatomic) NSDictionary* item; @end |
Connect in XCode the UIWebView and the UIActivityIndicator to the view controller – that concludes the UI setup.
Now on to the implementation. You will need to pass the RSS item from the RootViewController to the DetailsViewController by setting the item property (that you’ll do in a moment). For the moment assume the RSS item is set and create the viewDidLoad method:
- (void)viewDidLoad { [super viewDidLoad]; webView.delegate = self; webView.scalesPageToFit = YES; NSURL* url = [NSURL URLWithString:[item objectForKey:@"link"]]; [webView loadRequest:[NSURLRequest requestWithURL:url]]; NSLog(@"loading url..."); } |
When the view loads it will also start loading the page of the selected rss article. Add the following code to show/hide the activity indicator:
#pragma mark - #pragma mark UIWebViewDelegate messages - (void)webViewDidStartLoad:(UIWebView *)webView { loader.hidden = NO; } - (void)webViewDidFinishLoad:(UIWebView *)webView { loader.hidden = YES; } |
The only part left is to open the details viewcontroller when an item is selected from the table view in the root viewcontroller. There’s a small detail to look after since we have 2 table cells for each item – add this code back to the root viewcontroller:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView deselectRowAtIndexPath:indexPath animated:NO]; DetailsViewController *detailViewController = [[DetailsViewController alloc] initWithNibName:@"DetailsViewController" bundle:nil]; detailViewController.item = [rssItems objectAtIndex:floor(indexPath.row/2)]; [self.navigationController pushViewController:detailViewController animated:YES]; [detailViewController release]; } |
This code creates a new instance of the DetailsViewController and sets the item property to the selected rss item, then pushes it to the navigationController stack:
That’s about everything – you have a full RSS reader application. You can download the source code of the demo project here and don’t forget to leave me your comments.
·
Previous page of "Tutorial: Building advanced RSS reader"







Great article!, I also like you used GData I find it easier to use than NSXML in iOS.
Thanks Chuck, yes I’ve been looking into different benchmarks of XML parsing libraries and GData is not the fastest, but it’s a fine mesh of performance, lightness and ease of use. Thanks a lot for the comment
[...] Tutorial: Building advanced RSS reader RSS Reader (Part 1): Getting started with iPhone Development RSS Reader (Part 2): Creating a new iPhone Xcode project and setting up your environment RSS Reader (Part 3): What we’ll be building and which iPhone SDK features will be covered? RSS Reader (Part 4): Setting up the UITabBar and UITableView with delegates [...]
Great article, was wondering where does the fetchRSS method go and how it relates to muti threading
Cheers
Hi Robert,
have a look at the method called “dispatchLoadingOperation” it creates a new thread using the selector fetchRSS (in the web site you need to scroll a bit horizontally to see the code)
[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(fetchRss) object:nil]
this basically creates a new thread which when started will execute the fetchRss selector – have a look at the code of dispatchLoadingOperation it’s everything you need to spawn a new thread
[doc autorelease];
Why are you autoreleasing this? Why not just release it outright?
Hi Bob,
good question – I honestly don’t see why it is autoreleased, I might’ve had this code elsewhere, where it made sense, but the way it’s now definitely an immediate release is better.
Thanks for noticing!
Marin
Hi Martin,
Thanks for sharing, i’ve learnt a lot regarding threading from this. I’m new to objective-c so excuse me if im asking a silly question. I’m making some changes to this so that the data is stored to the DB and only runs fetchRss providing db is empty or lastUpdateTime > n hours.
Ive hit a brick wall and im not sure how to go about solving it. You’ve set RootViewController to comply RSSLoaderDelegate protocol. I want to change it so the appDelegate deals with the fetching of the rss and storing to the db and my viewcontroller to read from the DB only. Im running into a heap of problems. Could please advise how is a sensible thing to do? if not, could you please steer me in the right direction?
Thanks,
Dave
hi dave i’m glad the tutorial was oh help to u
first of all have a look what libraries there are for communicating with a database – the native c functions are a nightmare – i think there is one called fdbm which is quite easy to use if you know some sql.
i’d say when fetching rss items store them in the database and then store the current time (using nsdate) into the user defaults. when you finish fetching and saving the items call perforomSelector withObject withDelay to set a timeout for the next fetch.
in general maintainig an rss feed stored in a database is much more complicated task than just fetching the feed as in the tutorial. have a look for another good tut on how to deal with the db
when im back from the road would be a good idea to do a tut on database interaction from obj ckeep an eye on my rss;)
Hi,
I’m a newbie to iPad development and would like to transform this using a uisplitviewcontroller. I’ve tried to make this work but can’t really get it to go. Do have an example of how to do this?
Hi Colin,
don’t have an example straight away, but it should be pretty straight forward to turn the tableviewcontroller to a uisplitviewcontroller solution, maybe just google for “uisplitviewcontroller tutorial” …
best of luck, marin
hi everybody
i have a question that i hope one of you would be able to answer.
my question is How would i be able to add a reload or refresh button to this application to fetch new information.
thanks James
Hello!
)
Thanks for the tutorial, I liked it a lot.
But I have some problems. First of all I’m using a tab bar application. When I ran the app in ismulator and tap on a feed, it doesn’t open the webview(detailsview). If you cant tell me your iChat(aim) or anything else so we can talk it would be nice
Thanks for your time!
Hey, glad you liked the RSS tutorial! Now – if when you implement it inside your own app going between view controllers doesn’t work it means you probably didn’t copy over the code correctly – the scope of the tutorial is anyways to show you fetching RSS feeds, not insights of building iPhone apps
For more details on using navigation controller there’s a ton of other tuts out there: http://www.google.com/search?client=safari&rls=en&q=uinavigationcontroller+tutorial&ie=UTF-8&oe=UTF-8
Very good article!
best regards from germany!
Moin moin
Hi
great tutorial and app, I changed the rss feed to pull in a youtube feed of funny videos feed://gdata.youtube.com/feeds/base/videos?q=funny&client=ytapi-youtube-search&alt=rss&v=2
It works fine but I want to be able to show the thumbnails in the tableview, is this possible to do in your app. One more question to have you modified this app for xcode 4.2 in regards to ARC?
hey nolan! 1) you’ll have to show the thumbnails yourself, this tutorial shows only fetching the RSS feed 2) you can disable ARC per file, have a look here how to: http://maniacdev.com/2012/01/easily-get-non-arc-enabled-open-source-libraries-working-in-arc-enabled-projects/ … best, Marin
I have an RSS link in which there are rss links to pages such as AFL,Football, Basketball,Cricket etc. When I click that the RSS links are obtained. For example in case of AFL the rss link directs to the page
http://www.sportal.com.au/rss/australia/afl.xml
Here there are tags called “description” but there is only a part of description inside that tag. The full description is present inside the link present inside the tag “link”. Here for example the link is
http://www.sportal.com.au/afl-news-display/pies-duo-set-to-feature-160240
How can I get these full description from the above link? I’m in such a urgency. Any help is appreciated.
I have used the MWFeedParser. But still the problem exists. The problem is about the contents of parsing my friend. Inside the description tag there is no full description. Only part of it is given. But i need the full description. The full description is present inside the weblink inside the “link” tag. I need to get that data. How can i do that?
Hi Ganesh, you correctly figured out this is not an RSS issue. You’ll need to fetch the web page HTML code and then strip out the content that is interesting for you. Unfortunately there’s no simple way to do that. The webpage will contain more information which is not related to the post at all – like sidebar, menus, navigation, adverts, etc.
Hi!
Thank you for this great tutorial. It is simple and great. I was wondering how to implement a pull down method to refresh the view. I found a method on waterworld.com blog. Here is the code to reload the page:
-(void) pullDownToReloadActionFinished {
// add one data on top
[rssItems insertObject:[NSNumber numberWithInt: rand()] atIndex:0];
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject: [NSIndexPath indexPathForRow:0 inSection:0]]
withRowAnimation:UITableViewRowAnimationTop];
[self.pullToReloadHeaderView setLastUpdatedDate: [NSDate date]];
[self.pullToReloadHeaderView finishReloading:self.tableView animated:YES];
}
-(void) pullDownToReloadAction {
// finish reload after three seconds
[self performSelector:@selector(pullDownToReloadActionFinished) withObject:nil afterDelay: 3.0f];
}
But I can’t figure out how to just reload the rss feed! Can someone help me, please?
Thank you
Love your tutorial. Can you help me implement a search bar for information displayed in the tables? I’ve now used this for one app and 3 unique RSS feeds – If we can get the search to work, I would love to make a donation…
John
You write :
GDataXMLNode* title = [[[doc rootElement] nodesForXPath:@”channel/title” error:&error] objectAtIndex:0];
–> So here, nodesForXPath is asusmed to return an array of nodes.
NSArray* items = [[doc rootElement] nodesForXPath:@”channel/item” error:&error];
for (GDataXMLElement* xmlItem in items) {
[rssItems addObject: [self getItemFromXmlElement:xmlItem] ];
}
–> So here, nodesForXPath is asusmed to return an array of elements.
As GDataXMLElement inherits GDataXMLNode, and nodesForXPath returns an array of GDataXMLNode, how can you just write the last statement assuming it’s an array of GDataXMLElement ?
Hello,
I tried your tutorial and when I ran it after doing all the steps the Simulator crashed. I don’t know where is the problem.
Thank you
Hi there,
Great work on this! I was wondering if you had figured out how to deal with the special characters issue. For example, instead of displaying a parenthesis like this ( it displays (&8220; Any way to display them correctly? Thanks so much!!
hey Charles, I don’t think I know of an Objective-C class that converts html entities into characters but I imagine that it should be too hard to write one. Try googling for Objective-c and html entities, there might be something already out there to help you out
Thanks so much for the response, Marin. I found this: http://stackoverflow.com/questions/1105169/html-character-decoding-in-objective-c-cocoa-touch but I am not sure how that is supposed to interact with GDATAXMLNODE…Any suggestions?
Hey Charles, you are totally on the right track – I think this is the class you need (I followed a link from the page you posted) : https://github.com/mwaterfall/MWFeedParser/blob/master/Classes/GTMNSString%2BHTML.h
I am preparing a new RSS reader tutorial – one that makes use of all the iOS6 goodness, I’ll make use of this class as well in it.
Cheers
Hi Marin-
Great tutorial. You did a good job explaining things.
I’m trying to learn how to do something very similar for my work.
I can’t tell by the dates if this tutorial is really from 2010?
Would it be possible to update this tutorial or do a part 2 explaining how you could add thumbnails (ones that are included in the post).
If not, is there a good way to render the web view with larger text?
or does that have to do with the way the web page presents itself?
Hey Brian, yeah this is a relatively old tutorial – new one is in the works to match the new stuff in iOS6, but it won’t be out before the official launch of iOS6 because of the NDA. The text size – you should use CSS in your web page to make it bigger, or anything else related to the HTML itself.
[...] Building advanced RSS reader [...]
Great tutorial, thanks! There is however one thing I can’t seem to get done: Import multiple RSS feeds. I’ve got a table now and would love to get a unique RSS feed in each section of the table, but no matter what I try, each section seems to repeat the first RSS feed.. Any chance you could help? Thank you very much!
Hi Arno, as I already mentioned via email – the updated RSS Tutorial is coming out till the end of September, so you’ll have much better and flexible code to use. Cheers, Marin
[...] of the most popular articles on Touch Code Magazine is the complete example how to create an RSS reader app for the [...]
The way u explain and develop is pretty good
Hi,
Is there a way when we do not have internet that it shows an alarm instead of closing the app?
Check out the “Reachability” class from Apple to check whether there’s connection or not :]