overriding loadView in a UITableViewController subclass
Asked Answered
A

2

6

I am trying to setup a UITableViewController so that its tableView belongs to my custom subclass. My loadView method currently looks like this:

- (void) loadView {
   MyTableViewSubclass* tv = [[[MyTableViewSubclass alloc]initWithFrame: CGRectZero style: UITableViewStylePlain]autorelease];
   self.view = tv;
   self.tableView = tv;
}

I am getting crashes later on that go away if I comment out the above method. So something is missing. But what?

Apple's documentation says I should not be calling super in loadView. Which makes sense, because I want the view to have my class, not theirs.

Things I've tried that don't help:

  • Rewrite the loadView method so that it is creating a plain UITableView. This tells me that the source of the problem does not lie in the implementation of my subclass.
  • Call [super viewDidLoad] from my loadView method. From Apple's docs, it is unclear to me whether that method is called from loadView or afterwards. In any case, adding it to the end of my loadView method does not help.

One thing I've tried that does fix the problem, but defeats the purpose:

  • Comment out my loadView method.

EDIT: the crash is shown below. It happens after the user does some input. It also happens the same way if I am creating a plain UITableView instead of my subclass. There is a lot going on in the app, and something in my loadView override [or more likely, something missing from my override] is causing the state to be different, which in turn leads to the crash. But I don't see a good way to track what is different.

2011-09-08 12:44:59.591 MyAppName[97649:207] *** Terminating app due to uncaught exception 'NSRangeException', reason: '-[MyTableViewSubclass scrollToRowAtIndexPath:atScrollPosition:animated:]: row (0) beyond bounds (0) for section (0).'
Audit answered 8/9, 2011 at 16:22 Comment(2)
Could you let us know what the crash log says? -ThanksRoentgenogram
Can you add the console output from the crash?Gapes
A
12

Turns out I need to set the dataSource and delegate of my tableView as a part of loading. So when I do this, everything works fine:

- (void) loadView {
   MyTableViewSubclass* tv = [[[MyTableViewSubclass alloc]initWithFrame: CGRectZero style: UITableViewStylePlain]autorelease];
   tv.dataSource = self;
   tv.delegate = self;
   self.view = tv;
   self.tableView = tv;
}
Audit answered 8/9, 2011 at 18:4 Comment(2)
I have a question. Doesn't this approach defeat the purpose of MVC? Because now the controller only work with one type of table unless you subclass the controller and override loadView again?Oliva
On the question of MVC, the ViewController might be tied to the View now, but it fits better into an MVC model by separating the Controller from View. View code in the View, Controller code in the ViewController. Without a separation like this you are dumping all the code into one ViewController.Friederike
F
2

William's answer help me over the last hurdle too.

To add a swift example, the pattern I commonly use is:

class SomeTableViewController: UITableViewController {

    private var childView: SomeTableView! { return tableView as! SomeTableView }

    override func loadView() {
        tableView = SomeTableView(frame: UIScreen.mainScreen().bounds, style: .Plain)
        tableView.delegate = self
        tableView.dataSource = self
        view = tableView
    }

}

You are then free to refer to the customised view as childView in other places in the ViewController.

Friederike answered 19/8, 2015 at 23:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.