Crash when pushing cell to DetailView when it'

2019-09-05 22:19发布

问题:

I use this code to move to DetailView from TableView:

 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:TRUE];
  if(indexPath.row==0) {

      //Initialize the detail view controller and display it.
      Detail1ViewController *firstDetailController = [[Detail1ViewController alloc] initWithNibName:@"Detail1ViewController" bundle:nil];
      [self.navigationController pushViewController:firstDetailController animated:YES];
      [firstDetailController release];
}
else if(indexPath.row==1) {

    //2nd view
}
else if(indexPath.row==2) {

    //3rd view
}
}

The Detail1ViewController in the Storyboard is only a UIScrollView with no UIView behind it.

This is the Detail1ViewController.h:

#import <UIKit/UIKit.h>

@interface Detail1ViewController : UIViewController {
 IBOutlet UIScrollView *detail1Scroller;
}

@end

and for loading it the .m:

- (void)viewDidLoad
{
[super viewDidLoad];
[detail1Scroller setScrollEnabled:YES];
[detail1Scroller setContentSize:CGSizeMake(320,1100)];
// Do any additional setup after loading the view.
}

I've made the connection from "detail1Scroller" to the UISCrollView in Connections Inspector, and wrote "Detail1ViewController" as class for the Detail1ViewController in Identity Inspector. But the app crashes when I'm going to the detail view!

I've noticed that in the tutorial I'm following, the UIScrollView is placed upon a UIView, which I haven't done in my project. So I tried to create a TestViewController with the UIScrollView inside a UIView, but then the "detail1Scroller" Outlet isn't showing in the Connections Inspector as it does in the tutorial! Can someone please help me solve this, and also make it clear if I should use the UIScrollView with a UIView behind or not.

回答1:

A storyboard is a way to configure instances of view controllers, and instantiate them over and over again either automatically through segues or manually with code. When you're designing a view controller in the storyboard, you're not designing the class, you're designing a specific instance of the class. It's legal to have two instances of the same view controller class in the storyboard, with different view layouts.

That means that if you directly allocate an instance of your view controller class, it won't come with all of the UI that you specified in the storyboard. That's effectively whats happening with this code:

Detail1ViewController *firstDetailController = [[Detail1ViewController alloc] initWithNibName:@"Detail1ViewController" bundle:nil];
[self.navigationController pushViewController:firstDetailController animated:YES];
[firstDetailController release];

There's also a bit of confusion there in that you're specifying a NIB name even though you didn't design a XIB/NIB in Xcode.

To allocate a new copy of the view controller that you designed in your storyboard, you should use the -[UIStoryboard instantiateViewControllerWithIdentifier:] method. The identifier value should match the value in the storyboard identity inspector.

Your code should then look like this:

Detail1ViewController *firstDetailController = [[self storyboard] instantiateViewControllerWithIdentifier:/* my identifier */];
[self.navigationController pushViewController:firstDetailController animated:YES];

If you're using a storyboard for the view controller with this code, you should also consider using a segue to initiate this transition.