views:

1225

answers:

3

Hi,

I know this issue being mentioned before, but resolutions there didn't apply. I'm having a UINavigationController with an embedded UITableViewController set up using IB. In IB the UITableView's delegate and dataSource are both set to my derivation of UITableViewController. This class has been added using XCode's templates for UITableViewController classes. There is no custom UITableViewCell and the table view is using default plain style with single title, only.

Well, in simulator the list is rendered properly, with two elements provided by dataSource, so dataSource is linked properly. If I remove the outlet link for dataSource in IB, an empty table is rendered instead.

As soon as I tap on one of these two items, it is flashing blue and the GDB encounters interruption in __forwarding__ in scope of a UITableView::_selectRowAtIndexPath. It's not reaching breakpoint set in my non-empty method didSelectRowIndexPath. I checked the arguments and method's name to exclude typos resulting in different selector.

I recently didn't succeed in whether delegate is set properly, but as it is set equivalently to dataSource which is getting two elements from the same class, I expect it to be set properly. So, what's wrong?

I'm running iPhone/iPad SDK 3.1.2 ... but tried with iPhone SDK 3.1 in simulator as well.

EDIT: This is the code of my UITableViewController derivation:

#import "LocalBrowserListController.h"
#import "InstrumentDescriptor.h"

@implementation LocalBrowserListController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self listLocalInstruments];
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}

- (void)viewDidUnload {
    [super viewDidUnload];
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

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

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil)
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];

    if ( ( [entries count] > 0 ) && ( [indexPath length] > 0 ) )
        cell.textLabel.text = [[[entries objectAtIndex:[indexPath indexAtPosition:[indexPath length] - 1]] label] retain];

    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{
    if ( ( [entries count] > 0 ) && ( [indexPath length] > 0 ) )
    {
        ...
    }
}

- (void)dealloc {
    [super dealloc];
}

- (void) listLocalInstruments {
    NSMutableArray *result = [NSMutableArray arrayWithCapacity:10];

    [result addObject:[InstrumentDescriptor descriptorOn:[[NSBundle mainBundle] pathForResource:@"example" ofType:@"idl"] withLabel:@"Default 1"]];
    [result addObject:[InstrumentDescriptor descriptorOn:[[NSBundle mainBundle] pathForResource:@"example" ofType:@"xml"] withLabel:@"Default 2"]];

    [entries release];
    entries = [[NSArray alloc] initWithArray:result];
}

@end
+1  A: 

Try didSelectRowAtIndexPath. The selector as you typed it was missing the word "At" in the selector name.

Are you calling


- (void)selectRowAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(UITableViewScrollPosition)scrollPosition

If you are, then that will not call the delegate methods tableView:willSelectRowAtIndexPath: or tableView:didSelectRowAtIndexPath: You will have to call them yourself.

See the UITableView Reference.

For what it's worth I have not seen any difference in the table view behavior in the 3.0.x or 3.1.x releases.

Mark Thalman
Thanks for your response. And sorry for the typo, of course the method is including 'At' ... and I'm not calling selectRowAtIndexPath() programmatically ... it's all reacting on a user's tap. I read most parts of UITableView docs regarding creating them and managing selections.Appended code of my derived controller class above.
soletan
Integrated code like `if ( [(UITableView *)self.view delegate] != self ) { ... }` in `viewDidLoad` and before returning from `tableView:cellForRowAtIndexPath:` to check the delegate for matching `self`.Moreover, in iPad Simulator tapping existing items don't interrupt debugger, but select items w/o entering didSelectRowAtIndexPath ... looks like XCode behaving like Word 97 on editing 100th page in document.
soletan
+1  A: 

Well, after trying to retain the delegate of UITableView instance just to check for leaking memory with success, I investigated on that issue and stumbled over some tutorials on how to combine views and controllers using detached NIBs as I do here. This tutorial finally made me do the trick:

Combining View Controllers

Focusing on error in detail there were two UITableViewControllers ... one in main NIB set as root controller for a tabbed Navigation controller and a second time in referenced NIB used to provide a raw UITableView instance instead.

soletan
+5  A: 

Apple's documentation says that didSelectRowAtIndexPath:index will not be invoked when selectRowAtIndexPath:indexPath is called. To call didSelectRowAtIndexPath use the following:

[[tableView delegate] tableView:tableView didSelectRowAtIndexPath:index];

This basically invokes the delegate.

RPM
So what is this response good for? As stated more than two months ago I wasn't invoking selectRowAtIndexPath:indexPath. And nearly two months ago I provided solution to this problem myself ... maybe you should read the page first, don't you.
soletan
That's fairly ungrateful! One of the great things about StackOverflow is that is helps the community, not just an individual. Personally, I found this response to be just what I needed. Thanks RPM.
Darren Oster