1

I setup a project on XCode 4.3 and IOS 5 without using storyboards for both iPhone and iPad using the default Master/Detail setup from the create new project dialog.

The iPhone side works just fine. I select an option in the tableView and the detailViewController screen updates with the new information based on the selection.

My implementation of didSelectRowAtIndexPath is:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {  
        Shapes *currentShape = [self.shapesArray objectAtIndex:indexPath.row];  
        if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {  
            if (!self.detailViewController) {  
                self.detailViewController = [[[GeoDetailViewController alloc] initWithNibName:@"GeoDetailViewController_iPhone" bundle:nil] autorelease];  
            }  
            [self.navigationController pushViewController:self.detailViewController animated:YES];  
            [self.detailViewController populateDisplay:currentShape];  
        } else {  
            [self.detailViewController populateDisplay:currentShape];  
        }  
}  

However, when I run on the iPad, self.detailViewController does not exist. so the display doesn't update. I can still see it on the iPad screen, I just can't change anything on it. How do I reference it in the code so I can make changes to what is displayed?

Dave Sawers
  • 35
  • 2
  • 8

3 Answers3

1

In the master/detail template, Apple uses the following code in the MasterViewController (i.e. the one on the left):

- (void)viewDidLoad {
    [super viewDidLoad];
    self.detailViewController = (MYDetailViewController *)[[self.splitViewController.viewControllers lastObject] topViewController];
}

With the property on MasterViewController defined as:

@property (strong, nonatomic) MYDetailViewController *detailViewController;
Senseful
  • 86,719
  • 67
  • 308
  • 465
1

If you have a pointer to the split view controller itself, you can do:

[(GeoDetailViewController *)[[(UINavigationController *)[[splitViewController viewControllers] objectAtIndex:1] viewControllers] objectAtIndex:0] populateDisplay:currentShape];

To get the pointer to your split view, you will probably have to go via your app delegate:

UISplitViewController *splitViewController = [(MyAppDelegate *)[[UIApplication sharedApplication] delegate] splitViewController];

(assuming that you are using the default split view controller template - YMMV depending on how you have implemented it)

Note that when you create your split view, you must set the detail view controller to be a GeoDetailViewController - if you are not and you cannot for app design reasons, I can edit my answer to work around that.

jrtc27
  • 8,496
  • 3
  • 36
  • 68
  • The detail view controller is a GeoDetailViewController as far as I can see, but your solution doesn't work as it crashes with [UINavigationController populateDisplay:] unrecognized selector sent to instance ... But why does it say UINavigationController in the error? – Dave Sawers Feb 03 '12 at 19:54
  • When the viewControllers array is setup in didFinishLaunchingWithOptions, location 1 is set to the detailNavigationController, not the detailViewController I am looking for. I therefore need to somehow get to the detailViewController from the detailNavigationController. – Dave Sawers Feb 03 '12 at 20:09
  • So I found the answer by looking in location 0 of the viewControllers array of the returned detailNavigationController. It seems to work, but just wondering if this is a robust answer. Thanks very much for your help. – Dave Sawers Feb 03 '12 at 20:41
  • Answered my own question. This is not a robust way to find the detailViewController as it only works on an iPad with 5.0 on it. Earlier versions of IOS crash because it doesn`t find the detailViewController. So I`mm still looking for a definitive answer. – Dave Sawers Feb 03 '12 at 21:39
  • Is the *split view's* detail view controller a navigation controller then? – jrtc27 Feb 03 '12 at 22:23
  • I can't get enough information in these comments. The split view detail controller is setup using: – Dave Sawers Feb 03 '12 at 23:26
  • GeoDetailViewController *detailViewController = [[[GeoDetailViewController alloc] initWithNibName:@"GeoDetailViewController_iPad" bundle:nil] autorelease]; UINavigationController *detailNavigationController = [[[UINavigationController alloc] initWithRootViewController:detailViewController] autorelease]; – Dave Sawers Feb 03 '12 at 23:28
  • self.splitViewController = [[[UISplitViewController alloc] init] autorelease]; self.splitViewController.delegate = detailViewController; self.splitViewController.viewControllers = [NSArray arrayWithObjects:masterNavigationController, detailNavigationController, nil]; – Dave Sawers Feb 03 '12 at 23:29
  • 1
    That's the change I made that gets it working on IOS 5.0 but it crashes on all earlier versions because those controller arrays are not setup. I have therefore implemented the (so simple I must be stupid) alternative of setting up the masterViewController.detailViewController variable when the detail view is instantiated in the delegate. I am therefore giving the tick to the other solution which is what pointed me in that direction. Thanks again for your time. – Dave Sawers Feb 04 '12 at 12:59
  • If it is crashing, that implies that there is something fundamentally wrong with your implementation (not my code). What does it say when it crashes???? – jrtc27 Feb 04 '12 at 13:01
  • No, your code is good, but only for IOS 5.0. In previous versions, the viewControllers array at the second level (where you dig out index:0) doesn't exist. I think the problem is in the template code generated by XCode that doesn't seem to care about older versions of IOS. – Dave Sawers Feb 04 '12 at 14:06
1

I was puzzled by the templates implementation of the Master/Detail view. I asked a similar question:

How to update DetailView using MasterDetail Application Template

You can use the detailItem (id - so you can pass in a reference) property that is set up by default for the DetailViewController class.

Community
  • 1
  • 1
5StringRyan
  • 3,604
  • 5
  • 46
  • 69
  • Doh! The fix is so simple. In the delegate that instantiates both the master and detail view controllers, I simply assign the masterViewController.detailViewController property at that time. I can then use it elsewhere since I am always updating the same detail view depending on the selection from the tableView. Your thread pointed me in this direction so thanks. – Dave Sawers Feb 04 '12 at 13:02