Saving work with Three20! And write almost no code.

09/06/2010 § 42 Comments


I know, I know…RSS tutorials are all over the internet, but this one is not about it at all, really.

Yesterday I posted 5 reasons to use Three20 and perhaps one to do not do it. And then I thought that if the problem is documentation and documentation is really important, especially in the beginning, why not write a hands-on tutorial for the very basic stuff?

But every app needs an idea, therefore I had to come up with one too…and the idea is, of course, a RSS Feed Reader!

….

Let’s begin thinking what do we need to accomplish our quest.

First thing that comes to mind is a RSSFeedParser (oops, we already have a class name!). Then it would be nice to have an object that represents each feed instead of using dictionaries all over the place, right? We could name this class as FeedItem.

What attributes should our FeedItem own? It would be cool to let the feed reader know the title, date, description, category and maybe an image that is related to that feed? Oh, we also need the link so that the user is able to read the entire feed.

This is a good startup.

Let’s think about the UI. What I came up is pretty much like

It is basic, but also nice, isn’t it?

And what will we present while we are loading feeds? What if some internet connection error happens? What if there is no feed to present at all?

Let’s start presenting very simple screens for these cases (and as homework, you can make them better if you want to).

For the loading screen ..

For the error screen

And finally the No Feed screen:

Ok, this is pretty much a lot of work for one simple tutorial, isn’t it? Maybe not.

Let’s get started!

….

First of all you need to download the Three20 library (if you did not do it yet) and then create a Simple Application Project for the iPhone.

After that we can go thru the code.

….

Once you created your project, you should be able run it and see a browser presenting the Three20 project page. If you did not see it, you probably didn’t properly rename the Three20 folder from whatever it is named to three20, or you did not create the project at the very same directory that the library is installed.

So, instead of beginning with the sad part I will give to you the source code for the FeedItem and RSSFeedParser classes. Please, download these files and add them to your project as usual.

Now, if you look at your AppDelegate you will see an URL mapping from @”*” to TTWebController.


- (void)applicationDidFinishLaunching:(UIApplication *)application {
    TTNavigator* navigator = [TTNavigator navigator];
    navigator.persistenceMode = TTNavigatorPersistenceModeAll;
    TTURLMap* map = navigator.URLMap;
    [map from:@"*" toViewController:[TTWebController class]];
    if (![navigator restoreViewControllers]) {
         [navigator openURLAction:
            [TTURLAction actionWithURLPath:@"http://three20.info"]];
    }
}

This is the Three20 way to tell what view controller you want to present. Instead of allocating a view controller by yourself every time you want to present it, you just have to ask Three20 to present that URL and it will do the rest for you. The next step is to verify if there is some view controller to restore and if there isn’t, start with what should be our first view controller.

So, let’s add our own URL mapping so that we can open our view controller.


- (void)applicationDidFinishLaunching:(UIApplication *)application {
    TTNavigator* navigator = [TTNavigator navigator];
    navigator.persistenceMode = TTNavigatorPersistenceModeAll;
    TTURLMap* map = navigator.URLMap;
    [map from:@"*" toViewController:[TTWebController class]];
    [map from:@"tt://feed/" toViewController:
           [RSSFeedTableViewController class]];
    if (![navigator restoreViewControllers]) {
        [navigator openURLAction:
           [TTURLAction actionWithURLPath:@"tt://feed"]];
    }
}

XCode may have warned you that RSSFeedTableViewController was not created yet. So let’s add a new Three20 class that inherits from TTTableViewController and name it as RSSFeedTableViewController.


#import "RSSFeedTableViewController.h"
#import "RSSFeedDataSource.h"

@implementation RSSFeedTableViewController

- (id)init {
    if (self = [super init]) {
        self.variableHeightRows = YES;
    }
    return self;
}

- (void)viewDidLoad {
    [super viewDidLoad];

    self.navigationBarTintColor = [UIColor blackColor];
    self.title = @"iOS Guy RSS Feed";
}

#pragma mark --
#pragma mark TTModelViewController methods

- (void)createModel {
    RSSFeedDataSource *feedDataSource =
         [[RSSFeedDataSource alloc] init];
    self.dataSource = feedDataSource;
    TT_RELEASE_SAFELY(feedDataSource);
}

- (id<UITableViewDelegate>)createDelegate {
    return [[[TTTableViewVarHeightDelegate alloc]
                    initWithController:self] autorelease];
}

@end

Every TTTableViewController has a method called createDelegate that returns the delegate for the table view. This method is called by Three20 during it’s lifecycle. On this tutorial we will use the TTTableViewVarHeightDelegate as the delegate for our table view, because it enables the table view cell to tell the delegate what height it needs. This is really very handsome, because it saves some IFs and math.

Beyond the delegate we also need to provide the data source for the table view (just as the SDK approach), and this is done by the createModel method that is also called by Three20.

Now that we specified our dataSource and delegate we don’t have to bother with data handling nor table view cell rending anymore. This is why I took some few seconds to make the navigation bar black and add a title to the screen 😉

What should we do about the dataSource then?

Basically the Three20 concept from DataSource implies that it is responsible for the creation of the DataModel and for it’s handling.

Let’s create a class named RSSFeedDataSource that inherits from TTListDataSource and instantiate our model in it.


#import "RSSFeedDataSource.h"
#import "FeedItem.h"

@implementation RSSFeedDataSource

- (id)init {
    if (self = [super init]) {
        dataModel = [[RSSFeedDataModel alloc] init];
    }
    return self;
}

#pragma mark --
#pragma mark Memory Management methods

- (void)dealloc {
    [dataModel release];
    [super dealloc];
}

Now, let’s implement two methods from TTTableViewDataSource:


#pragma mark -
#pragma mark TTTableViewDataSource methods

- (id<TTModel>)model {
    return dataModel;
}

- (void)tableViewDidLoadModel:(UITableView *)tableView {
    NSArray *modelItems = [dataModel modelItems];
    NSMutableArray *updatedItems =
         [NSMutableArray arrayWithCapacity:modelItems.count];
    for (FeedItem *feedItem in modelItems) {
          TTTableMessageItem *item =
             [TTTableMessageItem itemWithTitle:feedItem.title
                                   caption:feedItem.category
                                   text:feedItem.description
                                   timestamp:feedItem.date
                                   imageURL:feedItem.imageURL
                                   URL:feedItem.link];

         [updatedItems addObject:item];
    }
    self.items = updatedItems;
}

The first method tells the DataSource what is it’s model. The second one is called when your model is ready and therefore is a good time to populate our table view with some table items.

Three20 let’s you define table items that are interface representations of your model item. Each table item is mapped to a table view cell that will render that item for you. As we are using a table view cell that comes within Three20, we don’t need to specify this mapping. But as you will need it someday, take a look on


- (Class)tableView:(UITableView*)tableView
               cellClassForObject:(id)object;

method from TTTableViewDataSource.

I chose the TTTableMessageItem as our item because it maps to a cell that already has all the features that we need to present our feeds, just as the very first screenshot.

It is also a task of the data source to handle our data model’s state so that the user can know what is going on. It is time to build those screens for loading, no feeds and internet connection problems. So, let’s add more 4 methods to our data source.


#pragma mark -
#pragma mark Error Handling methods

- (NSString *)titleForLoading:(BOOL)reloading {
    return @"Loading...";
}

- (NSString *)titleForEmpty {
    return @"No feed";
}

- (NSString *)titleForError:(NSError *)error {
    return @"Oops";
}

- (NSString *)subtitleForError:(NSError *)error {
    return @"The requested feed is not available.";
}

Yes, that was very easy. Wasn’t it?

The only missing piece of our application is the data model. This time we have to handle some states, so that we can notify the data source what is going on.

Basically the model fetches data and therefore it will have to connect to the internet, download our RSS and parse it into FeedItems. As all this work is asynchronous and while this all happens the model’s state change from “created” to “loading” and then to “failed” or “completed”.   We have to use some methods from TTModel to handle this state changes.

Our data model interface should look like this:


#import "RSSFeedParser.h"

@interface RSSFeedDataModel : TTModel<RSSFeedParserDelegate> {
     RSSFeedParser *parser;
     BOOL done;
     BOOL loading;
}

- (NSArray *)modelItems;

@end

Then plan is to use those two boolean variables to handle state changes, the parser to parse data from the web site and the modelItems method to retrieve an array of FeedItems when the model is done.


#import "RSSFeedDataModel.h"

@implementation RSSFeedDataModel

- (NSArray *)modelItems {
    return [parser feedItems];
}

#pragma mark --
#pragma mark TTModel methods

- (void)load:(TTURLRequestCachePolicy)cachePolicy more:(BOOL)more {
    done = NO;
    loading = YES;
    parser = [[RSSFeedParser alloc] initWithContentsOfURL:
              [NSURL URLWithString:@"https://iosguy.com/feed/"]];
    parser.delegate = self;
    [parser parse];
}

- (BOOL)isLoaded {
    return done;
}

- (BOOL)isLoading {
    return loading;
}

#pragma mark --
#pragma mark RSSFeedParserDelegate methods

- (void)rssFeedParserDidFinishParsing
              :(RSSFeedParser *)rssFeedParser {
   done = YES;
   loading = NO;
   [self didFinishLoad];
}

- (void)rssFeedParser:(RSSFeedParser *)rssFeedParser
           didFailWithError:(NSError *)error {
   done = YES;
   loading = NO;

   [self didFailLoadWithError:error];
}

- (void)dealloc {
   [parser release];
   [super dealloc];
}

@end

The code is pretty legible and easy to understand. You should already be able to run the code and see it working.

And if you are the kind of guy that like to see it working before start copying code, you can get the project source code here.

Now take a time to double check the code, debug it and see how it works.

I have two cool surprises for you!

First: Did you try to click on any feeds?

Two: What do you think to be able to pull the table view down to refresh it’s content?

Fortunately we can do this changing just one line of our code. Go back to our view controller and change the createDelegate method to use the TTTableViewDragRefreshDelegate:


- (id<UITableViewDelegate>)createDelegate {
     return [[[TTTableViewDragRefreshDelegate alloc]
         initWithController:self] autorelease];
}

Your app should look like this when you pull the table view down (and when you release it, it will automatically refresh it’s content).

Awesome!

Advertisement

Tagged: , , , , , , , ,

§ 42 Responses to Saving work with Three20! And write almost no code.

  • Chait says:

    Perfect! That’s exactly what I am looking for.

  • Stan says:

    This was really helpful. I had done some three20 data source and model classes but I had not seen how to do an XML parser, until now. Thanks!

  • mapedd says:

    Hi, did you consider making more Three20 tutorials, for example about something like TTMoviePlayer or TTLauncherView?

    p.s. awesome tutorial!

  • mapedd says:

    It’s great that you want to make more of them!

    Right now i’m trying to port your solution and parse another rss, namely: http://phatflysneakers.eu/rss
    i’ve made that images are downloaded, but the title or link do not show at all, maybe you have some hint for that?

    • mapedd says:

      right now i’m able to get something like that:

      it’s strange becouse both xmls have field like pubDate, title and link.

      • It seems to me that your pubDate has not the same date format I am using on WordPress.

        Try to do not handle the pubDate at all to see if the other fields like the description shows up.

        If that is the case, you will have to figure out what is the correct mask to handle your pubDate.

  • mapedd says:

    there also a drawback in your solution, pull-to-reload doesn’t work properly, activity indicator doesn’t show up, and after triggering the refresh action, the blueish field with arrow stop , it don’t scroll up to the good position like in facebook.app

    • Hmmm…the activity indicator is not showing up, but the content is being refreshed.
      In this tutorial I used the very default Three20 “drag to refresh” feature, which is added to your project just by returning a TTTableViewDragRefreshDelegate object instance in the createDelegate method.

      It should work perfectly.

      In fact it is not that beautiful but is a great feature and this is why I changed completely the look and feel (and the activity indicator shows up) in a project I am working on at my company (nothing to do with RSS readers).

      Anyways, this tutorial was written using iOS SDK 4.0. Did you download the source code or you copied the code (on the very first time)?

      You can send me an e-mail if you want to discuss further (cezarsignori@gmail.com).

  • jonathan says:

    I am a noob iPhone developer and I wanted to have a variable height for my rows depending of their content for a feed in my app. I use “TTTableviewcontroller” with “TTTablemessageitem” to display that feed but cant make “TTTableViewVarHeightDelegate” work with them.

    Do you know if this class is compatible with “TTTableviewcontroller” / “TTTablemessageite” ?

    Thank you in advance for your answer ! And thank you for your blog, it’s a great read !

    • Hey!

      I appreciate your feedback!

      Once your controller does:

      
      - (id)createDelegate {
      	return [[[TTTableViewVarHeightDelegate alloc] 
                   initWithController:self] autorelease];
      }
      
      

      And your view controller inherits from TTTableViewController…you can set the following variable in your init method:

      
      self.variableHeightRows = YES;
      
      

      Then you should implement the following method on your TableItemCell class:

      
      + (CGFloat)tableView:(UITableView*)tableView 
                   rowHeightForObject:(id)object {
          return your feed height here;
      }
      
      

      Since you are using TTTableMessageItem, you probably want to inherit from TTTableMessageItemCell and modify your DataSource to map the TTTableMessageItem to your custom cell class.

      
      - (Class)tableView:(UITableView *)tableView 
                             cellClassForObject:(id)object { 
         if ([object isKindOfClass:
                    [TTTableMessageItem class]]) {  
              return [MyTableMessageItemCell class];  
          } else {  
              return [super tableView:tableView 
                               cellClassForObject:object];  
          }
      }
      
      

      Hope this helps you.

  • Rajiv Kumar says:

    Hey Cezar

    Thanks for the wonderful RSS tutorials. It is amazing and am trying for same from many days but you help me out. 🙂

    Warm regards,
    Rajiv

  • umar says:

    Hi

    Thanks very help ful tutorial.

    My problem is :

    I want to change TTStyledTextLabel textColor and font for different
    strings.

    I want to use two types of TTStyledTextLabel.
    One for Title of book name and other is for Author Name
    For Title of book I want bold text light blue textColor and
    for Author Name I want simple text (no bold) with dark blue textColor

    and both should be TTStyledTextLabel.

    How I can do this.

    please help me

  • umar says:

    Hi

    Thanks for reply

    I have one more problem.
    I use your method to show feed in my app.

    I have Three CustomCell

    @interface FeedItemCell : TTTableLinkedItemCell
    {
    NSString *feedTitle, *dateLabel ,* userImage, …;

    }

    @interface NoteItemCell : FeedItemCell
    {
    NSMutableArray *imagesArray;
    …..
    }
    @interface WebLinkItemCell : FeedItemCell
    {
    TTImageView *webImage;
    ….
    }

    These are my Custom Cells.

    The problem is when All the feed Shows on the screen and I scroll the TTTableViewCell the e.g NotItemCell images shows on other NotItemCell that have no images (TTTableViewCell reusing cell contents)

    How I solve this problem in my Feed.

    Please help me how I can remove contents of TTTableViewCell if contents already layout on cell.

    Thanks in advance.

    • I don’t know if I got what is your problem…but cell-reuse-related-issues can be fixed by overriding the setObject method instead of setting each cell’s property.

      – (void)setObject:(id)pObject {
      if (tableItem != pObject) {
      [tableItem release];
      tableItem = [pObject retain];

      textLabel.text = tableItem.text;
      // and so on..
      }
      }

  • umar says:

    Hi

    I am using Three20 in my project to show Feed in TTTableViewCells.

    I am using TabBar to filter feed on different types such as weblinks,
    other feed etc…

    The problem is that When I Select weblinks tap I have to send request on server to fetch weblinks data and update my view ( in this case TTTableViewCells)

    But my program crashes “Error Message” is
    [NFCString – (void)tableViewDidLoadModel: (UITableView*)tableView
    unrecognized selector sent to instance……

    Please help “What function of TTTableViewController should call so that it fetch
    data from server and update my views”.

    Thanks

    Below is my code to fetch feed from server

    ///FeedTTTableViewController

    #pragma mark –
    #pragma mark UITabBar delegate

    – (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item {
    if( item.tag == weblink)
    [ self sendRequestForWebLinks];

    }

    #pragma mark —
    #pragma mark TTModelViewController methods

    – (void)createModel {

    FeedDataSource *feedDataSource = [FeedDataSource
    sharedFeedDataSource];

    self.dataSource = feedDataSource;

    TT_RELEASE_SAFELY(feedDataSource);
    }

    – (id)createDelegate {
    return [[[TTTableViewDragRefreshDelegate alloc]
    initWithController:self] autorelease];

    }

    /// Feed DataSource
    – (void)tableViewDidLoadModel:(UITableView *)tableView {

    NSLog(@”I am in tableViewDidLoadModel %d”,count++ );
    NSMutableArray *modelItems = [NSMutableArray arrayWithArray:
    [feedDataModel modelItems]];
    self.items = modelItems;

    TTTableMoreButton *button = [TTTableMoreButton itemWithText:@”Loading
    More…”];
    [self.items addObject:button];

    }

    – (void)tableView:(UITableView*)tableView cell:(UITableViewCell*)cell
    willAppearAtIndexPath:(NSIndexPath*)indexPath {
    [super tableView:tableView cell:cell
    willAppearAtIndexPath:indexPath];
    if (indexPath.row == self.items.count-1 && [cell isKindOfClass:
    [TTTableMoreButtonCell class]]) {
    TTTableMoreButton* moreLink = [(TTTableMoreButtonCell *)cell
    object];
    moreLink.isLoading = YES;
    [(TTTableMoreButtonCell *)cell setAnimating:YES];
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
    [self.model load:TTURLRequestCachePolicyDefault more:YES];
    }

    }

    //FeedModel

    – (void)load:(TTURLRequestCachePolicy)cachePolicy more:(BOOL)more {

    if (!self.isLoading) {
    if (more) {
    self.page += 1;
    } else {
    [feedItemsDictionary removeAllObjects];
    self.page = 1;
    }

    [ self sendRequestForFeed];
    }

    But my program crashes “Error Message” is
    [NFCString – (void)tableViewDidLoadModel:(UITableView*)tableView
    unrecognized selector sent to instance……

    Please help “What function of TTTableViewController call that fetch
    data from server and update my views”

  • jack says:

    Hi, there. The link for the source code is broken. Could you please repost it? big thanks..

  • Ruben says:

    Hy! First of all I would like to say very thanks for your tutorial. Im working on the practice finall project of my career and I discover Three20 by a chance, now Im pretty busy trying to learn how to use it, because as you said, theres not a good documentation.
    About this tutorial, I only would like to ask you if you are totally sure the screen “loading” works fine. I integrate some parts of your tutorial in my application, but Im not able to get the screen loading and when the data base is not enough fast (Im working with an enormous data base) iOS close my application.

    Will check with patient, if I discover something I will send you a mail 🙂
    Greetings from Spain and again, thanks for your work 🙂

    • Yup, you should be able to just download the source code and have the loading working.

      The idea behind implementing the loading mechanism is pretty much what this tutorial suggests, but you should look into your problem (the way data is being loaded by your application) anyways. The reason why I am telling you this, is because I worked on Salesforce Chatter for iPad and the loading mechanism is somewhat different 🙂

      Thanks!

      • Ruben says:

        Hi! Thanks for answer! I just coming back from my holidays. In Spain we had “Semana Santa” which for non religious people means 4 days of holidays 🙂

        To loading data i created an API in php. So the application ask for data to the php scripts and get an XML file. I was working with JSON but decided to change to XML to use exactly the same code structure you use in this tutorial, but I still have the problem, if the database is not enough fast iOS decided my application is not working. Its weird, because using the same way within the TTPhotoThumb it works perfect.

        I have to implement some controls to finish one part, and then will put all my efford trying to solve this. I will let you know if I find a solution 🙂

      • Ruben says:

        I was trying your code and it looks it doesn’t work on your tutorial too. When you open the application for the first time, the screen shows black while the data of the TTTable is loading. Once the data is loaded it shows the full table.

      • Ruben says:

        I think the problem is with the method “isLoading”, the application calls this method before and after the “load” method, but never during. So, after load, the method isLoading is without sense, and if you set “loading=yes” by default, the applicaton stop and never execute the load method.

        Im looking for a solution 🙂

      • Ruben says:

        I finally solved it.

        I think the problem is you have used you your own xml parser and you should use de Three20 parser.
        The way in the TTDataModel works is very interesting. So, if someone have a similar problem they can orientate with the TTFacebook project in the samples folder or with the TTTwiter project which is quite similar.

        Un saludo!!

  • Cory says:

    Thanks so much for the tutorial! It is almost perfect for the needs of the app I’m developing.

    I just need help with one thing… I know it is possible to have the table to push a “DetailViewController” when it is touched, but I can’t figure out how to do it. Basically, I need to have the app load the full contents of the article in a detail view when a table item is touched. If you could help, that would be great.

    Thanks again!

  • Your tutorials are awesome! Thanks so much!

  • toliver182 says:

    Hi, firstly thanks for this tutorial its a great help.

    I need my list to display slightly differently. I just want the title to display. so i figured change this

    TTTableMessageItem *item =
    [TTTableMessageItem itemWithTitle:feedItem.title
    caption:feedItem.category
    text:feedItem.description
    timestamp:feedItem.date
    imageURL:feedItem.imageURL
    URL:feedItem.link];

    to this.

    TTTableMessageItem *item =
    [TTTableMessageItem itemWithText:feedItem.title
    URL:feedItem.link];

    It compiles and runs however the Cell height is still in large as if all content were there.
    Where in the code is the cell height is set/ deducted?

    how can i amend this?

    Many thanks.

  • rocky says:

    thank you, you saved me a lot of time with this! much appreciated fella.

  • rocky says:

    .. although found it doesn’t work perfectly. If you use TTNavigator to load the viewController, it loads the entire RSS feed first, and then parses the content and displays it in the tableview. You never see the “Loading” screen 😦 will try and find out whats wrong and report back.

  • I managed to get my feed showing in the app but can’t seem to get rid of the format tags such as and so on. (shown in the image here) http://d.pr/cEme

    any ideas how to resolve this?

  • Josh says:

    Hello! I tried to compile your app, but it said the three20 framework was missing.

    error: /Users//RSSFeedReader/../three20/src/Three20.bundle: No such file or directory

    I’m pretty new at this, so I could be doing something silly. I also tried to follow your instructions, but there wasn’t anything in my file

    Also, would you mind posting the updated source code with everything bundled?

    Thanks!

    • Hi Josh,

      that is probably because Three20 has some newer versions than the one I used when this tutorial was written.

      Unfortunately I can’t work on this right now..so I think you should go to the official web site, download a sample empty project and then follow this tutorial.

      Thanks,
      Cezar

  • Ferrantv says:

    Hi I follow your GREAT tutorials!

    I want create app for my University, I follow your TTLauncherView and work fine, follow your RSS tutorial and work fine but when add the RSS inside TTLauncherView Project the feeds not open. Showme the feeds but click a feed and return to TTLauncherView.

    I don’t understand!

    Can you helpme?

    THANKS A LOT!!!!!

  • hello (my apologies for my english) thank you very much for this tutorial, it allowed me to understand many things about three20. But I have a little trouble integrating into a tabbar. So I tried again with your code without modification, but I never arrived to open ttwebcontroller when i click on a cell when I have integrated it in a tabbar. Would you have an idea ? i search whit a friend since few days … I despair a little -.- .. if you can help me i promess i will make a tutorial in french in order to explain how use your tutorial in a tabbar (for never forget it ^^).

    This is my AppDelegate .. : (my firstviewcontroller is your RSSviewcontroller)

    #import “AppDelegate.h”

    #import “FirstViewController.h”

    #import “SecondViewController.h”

    @implementation AppDelegate

    – (void)applicationDidFinishLaunching:(UIApplication *)application {

    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

    // Do any additional setup after loading the view, typically from a nib.
    TTNavigator* navigator = [TTNavigator navigator];

    [navigator setPersistenceMode:TTNavigatorPersistenceModeAll];

    TTURLMap* map = navigator.URLMap;

    [map from:@”*” toViewController:[TTWebController class]];
    [map from:@”tt://feed/” toViewController:[FirstViewController class]];

    if (![navigator restoreViewControllers]) {
    [navigator openURLAction:[TTURLAction actionWithURLPath:@”tt://feed”]];
    }

    // Override point for customization after application launch.
    UIViewController *viewController1 = [[FirstViewController alloc] initWithNibName:@”FirstViewController” bundle:nil];
    UIViewController *viewController2 = [[SecondViewController alloc] initWithNibName:@”SecondViewController” bundle:nil];
    self.tabBarController = [[UITabBarController alloc] init];
    self.tabBarController.viewControllers = @[viewController1, viewController2];
    self.window.rootViewController = self.tabBarController;
    [self.window makeKeyAndVisible];

    }

    – (BOOL)navigator:(TTNavigator*)navigator shouldOpenURL:(NSURL*)URL {
    return YES;
    }

    – (BOOL)application:(UIApplication*)application handleOpenURL:(NSURL*)URL {
    [[TTNavigator navigator] openURLAction:[TTURLAction actionWithURLPath:URL.absoluteString]];
    return YES;
    }

    @end

    • Hi Pierre,

      There is sometime since I worked with Three20, but as far as I remember you need to:

      1. Inherit UITabBarController’s init, viewDidLoad, shouldAutorotateToInterfaceOrientation and tabBarController:didSelectViewController:
      2. On the app delegate, instead of adding the tab controller into the window, call [map from:kAppRootURLPath toSharedViewController:[YourTabBarController class]];

      The main idea behind inheriting those methods from UITabBarController, is to call setTabURLs (from UITabBarController (TTCategory)) and set the delegate to self.

      If you need further help, please contact me via e-mail.

      Thanks,
      Cezar

Leave a Reply to Ryan Garchinsky Cancel reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

What’s this?

You are currently reading Saving work with Three20! And write almost no code. at iOS Guy.

meta

%d bloggers like this: