Note that there are some explanatory texts on larger screens.

plurals
  1. POUITableView issue when using separate delegate/dataSource
    text
    copied!<p><strong>General Description:</strong></p> <p>To start with what works, I have a <code>UITableView</code> which has been placed onto an Xcode-generated view using Interface Builder. The view's File Owner is set to an Xcode-generated subclass of <code>UIViewController</code>. To this subclass I have added working implementations of <code>numberOfSectionsInTableView: tableView:numberOfRowsInSection:</code> and <code>tableView:cellForRowAtIndexPath:</code> and the Table View's <code>dataSource</code> and <code>delegate</code> are connected to this class via the File Owner in Interface Builder.</p> <p>The above configuration works with no problems. The issue occurs when I want to move this Table View's <code>dataSource</code> and <code>delegate</code>-implementations out to a separate class, most likely because there are other controls on the View besides the Table View and I'd like to move the Table View-related code out to its own class. To accomplish this, I try the following:</p> <ul> <li>Create a new subclass of <code>UITableViewController</code> in Xcode</li></li> <li>Move the known-good implementations of <code>numberOfSectionsInTableView:</code>, <code>tableView:numberOfRowsInSection:</code> and <code>tableView:cellForRowAtIndexPath:</code> to the new subclass</li> <li>Drag a <code>UITableViewController</code> to the top level of the <em>existing</em> XIB in InterfaceBuilder, delete the <code>UIView</code>/<code>UITableView</code> that are automatically created for this <code>UITableViewController</code>, then set the <code>UITableViewController</code>'s class to match the new subclass</li> <li>Remove the previously-working <code>UITableView</code>'s existing <code>dataSource</code> and <code>delegate</code> connections and connect them to the new <code>UITableViewController</code></li> </ul> <p>When complete, I do not have a working <code>UITableView</code>. I end up with one of three outcomes which can seemingly happen at random:</p> <ul> <li>When the <code>UITableView</code> loads, I get a runtime error indicating I am sending <code>tableView:cellForRowAtIndexPath:</code> to an object which does not recognize it</li> <li>When the <code>UITableView</code> loads, the project breaks into the debugger without error</li> <li>There is no error, but the <code>UITableView</code> does not appear</li> </ul> <p>With some debugging and having created a basic project just to reproduce this issue, I am usually seeing the 3rd option above (no error but no visible table view). I added some NSLog calls and found that although <code>numberOfSectionsInTableView:</code> and <code>numberOfRowsInSection:</code> are both getting called, <code>cellForRowAtIndexPath:</code> is not. I am convinced I'm missing something really simple and was hoping the answer may be obvious to someone with more experience than I have. If this doesn't turn out to be an easy answer I would be happy to update with some code or a sample project. Thanks for your time!</p> <p><strong>Complete steps to reproduce:</strong></p> <ul> <li>Create a new iPhone OS, View-Based Application in Xcode and call it <code>TableTest</code></li> <li>Open <code>TableTestViewController.xib</code> in Interface Builder and drag a <code>UITableView</code> onto the provided view surface.</li> <li>Connect the <code>UITableView</code>'s <code>dataSource</code> and <code>delegate</code>-outlets to File's Owner, which should already represent the <code>TableTestViewController</code>-class. Save your changes</li> <li>Back in Xcode, add the following code to <code>TableTestViewController.m:</code></li> </ul> <hr> <pre><code>- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { NSLog(@"Returning num sections"); return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { NSLog(@"Returning num rows"); return 1; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { NSLog(@"Trying to return cell"); static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease]; } cell.text = @"Hello"; NSLog(@"Returning cell"); return cell; } </code></pre> <ul> <li><p>Build and Go, and you should see the word <code>Hello</code> appear in the <code>UITableView</code></p></li> <li><p>Now to attempt to move this <code>UITableView</code>'s logic out to a separate class, first create a new file in Xcode, choosing <code>UITableViewController</code> subclass and calling the class <code>TableTestTableViewController</code></p></li> <li>Remove the above code snippet from <code>TableTestViewController.m</code> and place it into <code>TableTestTableViewController.m</code>, replacing the default implementation of these three methods with ours.</li> <li>Back in Interface Builder within the same <code>TableTestViewController.xib</code>-file, drag a <code>UITableViewController</code> into the main IB window and delete the new <code>UITableView</code> object that automatically came with it</li> <li>Set the class for this new <code>UITableViewController</code> to <code>TableTestTableViewController</code></li> <li>Remove the <code>dataSource</code> and <code>delegate</code> bindings from the existing, previously-working <code>UITableView</code> and reconnect the same two bindings to the new <code>TableTestTableViewController</code> we created.</li> <li>Save changes, Build and Go, and if you're getting the results I'm getting, note the <code>UITableView</code> no longer functions properly</li> </ul> <p><strong>Solution:</strong> With some more troubleshooting and some assistance from the <a href="https://devforums.apple.com/message/5453" rel="noreferrer">iPhone Developer Forums</a>, I've documented a solution! The main <code>UIViewController</code> subclass of the project needs an outlet pointing to the <code>UITableViewController</code> instance. To accomplish this, simply add the following to the primary view's header (<code>TableTestViewController.h</code>):</p> <pre><code>#import "TableTestTableViewController.h" </code></pre> <p>and</p> <pre><code>IBOutlet TableTestTableViewController *myTableViewController; </code></pre> <p>Then, in Interface Builder, connect the new outlet from File's Owner to <code>TableTestTableViewController</code> in the main IB window. No changes are necessary in the UI part of the XIB. Simply having this outlet in place, even though no user code directly uses it, resolves the problem completely. Thanks to those who've helped and credit goes to BaldEagle on the iPhone Developer Forums for finding the solution.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload