views:

172

answers:

3

Hiya,

I'm pretty new to developing with Cocoa Touch/XCode and I came across a problem.

I'm making a sort of RSS reader for a newssite and I have 5 views of tables navigated with 5 tabs in a TabBarController. If someone selects a newsitem I want another view to open showing the complete newsitem. My problem is that it won't work.

This is my code:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection(NSInteger)section{
    return [[[self rssParser]rssItems]count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"rssItemCell"];
    if(nil == cell){
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"rssItemCell"]autorelease];
    }
    cell.textLabel.text = [[[[self rssParser]rssItems]objectAtIndex:indexPath.row]title];
    cell.detailTextLabel.text = [[[[self rssParser]rssItems]objectAtIndex:indexPath.row]description];
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    [[self appDelegate] setCurrentlySelectedBlogItem:[[[self rssParser]rssItems]objectAtIndex:indexPath.row]];
    [self.appDelegate loadNewsDetails];
}

And it calls this method in my delegate:

-(void)loadNewsDetails{
    [[self rootController]pushViewController:detailController animated:YES];
}

Please tell me what I'm doing wrong. BTW I do not want to use a NavigationController, just the tabbar I'm using.

Thanks in advance,

Ken

A: 

Two points:

  1. Why don't you want to use a navigation controller?
  2. pushViewController:animated: is a method of UINavigationController. If you're not using a UINavigationController, you can't use this method and get the sliding animation. Your only other real option at this point would be to use presentModalViewController:animated:, which will display a modal view that slides up from the bottom. You'll need to provide a way of dismissing it when you're done.

If you still want the sliding animation but don't want the UINavigationBar, you could use a UINavigationController but hide the navigation bar with the setNavigationBarHidden:animated: method. It's hard to say what the right solution is without knowing what you want the end result to be.

Alex
A: 

I agree with Alex that you should try to use a Navigation controller if you can, but if you don't want to, no worries, you can still get a sliding animation that's very similar. The code below will show a view taking into account interface orientation and pushing from the right regardless of device position, same for the hiding method.

- (void) pushMyView:(UIInterfaceOrientation)interfaceOrientation {
    [self.view addSubview:myNewView.view];

    CATransition *animation = [CATransition animation];
    [animation setDuration:0.3];
    [animation setType:kCATransitionPush];

    // Compute direction by orientation
    if (UIInterfaceOrientationPortrait == interfaceOrientation) {
        [animation setSubtype:kCATransitionFromRight];
    } else if (UIInterfaceOrientationLandscapeLeft == interfaceOrientation) {
        [animation setSubtype:kCATransitionFromBottom];
    } else if (UIInterfaceOrientationLandscapeRight == interfaceOrientation) {
        [animation setSubtype:kCATransitionFromTop];
    } else if (UIInterfaceOrientationPortraitUpsideDown == interfaceOrientation) {
        [animation setSubtype:kCATransitionFromLeft];       
    }

    [animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];

    [[window layer] addAnimation:animation forKey:@"ShowMyNewView"];
}

-(void) hideMyView:(UIInterfaceOrientation)interfaceOrientation {
    [myNewView.view removeFromSuperview];

    CATransition *animation = [CATransition animation];
    [animation setDuration:0.3];
    [animation setType:kCATransitionPush];

    // Compute direction by orientation
    if (UIInterfaceOrientationPortrait == interfaceOrientation) {
        [animation setSubtype:kCATransitionFromLeft];
    } else if (UIInterfaceOrientationLandscapeLeft == interfaceOrientation) {
        [animation setSubtype:kCATransitionFromTop];
    } else if (UIInterfaceOrientationLandscapeRight == interfaceOrientation) {
        [animation setSubtype:kCATransitionFromBottom];
    } else if (UIInterfaceOrientationPortraitUpsideDown == interfaceOrientation) {
        [animation setSubtype:kCATransitionFromRight];      
    }

    [animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]]; 

    [[window layer] addAnimation:animation forKey:@"HideMyNewView"];    
}
Sangraal
A: 

Using a tab bar controller doesn't mean you can't use one or more navigation controllers as well. For instance, the iPod app does this, and it's how users are going to expect your app to behave.

You should just add five UINavigationController objects to your MainWindow.xib file, one under each tab. Then just set your RSS table view as the root view controller of each of the navigation controllers. (I'm assuming you'll need to change behavior based on which tab the view is under; just use (MyAppDelegate *)[[UIApplication sharedApplication] delegate].tabBarController.selectedIndex in your viewDidLoad method to set up your table).

Then to push your detail view controller, you'll just do the following idiomatic code:

DetailController *detailController = [[DetailController alloc] initWithItem:[self.rssParser.rssItems objectAtIndex:indexPath.row]];
[self.navigationController pushViewController:detailController animated:YES];
[detailController release];

Of course you'll have to add an initWithItem: method to your detail controller:

-(id)initWithItem:(RSSItem *)item {
    if (self = [super initWithNibName:@"DetailController" bundle:nil]) {
        self.item = item;
    }

    return self;
}

Generally, you'll want to distribute the control over what item is displayed to the view controllers doing the displaying, rather than trying to maintain central control in your app delegate.

Frank Schmitt