tableView didSelectRowAtIndexPath doesn't work

2019-07-07 00:30发布

问题:

In first place I would like to say that I'm only making this question, because I would like to understand what is happening.

I opened an old Xcode project (a very simple one) in a fresh installation on Xcode5. When I realize that it doesn't work on iOS 7. Why? Don't know..

I saw some other questions, didn't get any useful answer, so I made a simple test. In the UITableViewController all works fine except on didSelectRowAtIndexPath

Check it out

RootViewController.h:

@interface RootViewController : UITableViewController

@property (strong, nonatomic) NSMutableArray *items;
@end

RootViewController.m In viewDidLoad I init the array (with some strings).

Implement the dataSource and delegate methods (and yes I set the delegate and dataSource to the tableView)

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [_items 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];
    }

    // Configure the cell...
    cell.textLabel.text = [_items objectAtIndex:indexPath.row];

    return cell;
}

The problem is here:

    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Navigation logic may go here, for example:
    // Create the next view controller.
    DetailViewController *detailViewController = [[DetailViewController alloc] initWithNibName:@"DetailViewController" bundle:nil];

    // Push the view controller.
    [self.navigationController pushViewController:detailViewController animated:NO];

    detailViewController.detailLabel.text = [_items objectAtIndex:indexPath.row];
}

DetailViewController is a simple UIViewController:

(yes, I set the IBOutlet on nib file)

@interface DetailViewController : UIViewController
@property (weak, nonatomic) IBOutlet UILabel *detailLabel;

@end

The problem is that this doesn't work on iOS7, the label in DetailViewController doesn't get updated. I try to set the label text before and after of pushViewController.

This works on all previous versions of iOS.

Why is not working on iOS 7 ??

The only way I get this working is, like I saw on this other question:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Navigation logic may go here, for example:
    // Create the next view controller.
    DetailViewController *detailViewController = [[DetailViewController alloc] initWithNibName:@"DetailViewController" bundle:nil];

    // Push the view controller.
    [self.navigationController pushViewController:detailViewController animated:YES];

    dispatch_async(dispatch_get_main_queue(), ^{
        detailViewController.detailLabel.text = [_items objectAtIndex:indexPath.row];
    });
}

Can somebody help me out to understand what is going on here??

Thanks!

_

EDIT

it also works like this:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Navigation logic may go here, for example:
    // Create the next view controller.
    DetailViewController *detailViewController = [[DetailViewController alloc] initWithNibName:@"DetailViewController" bundle:nil];

    // Push the view controller.
    [self.navigationController pushViewController:detailViewController animated:YES];

    if (detailViewController.view) {
        // do notihing
    }
    detailViewController.detailLabel.text = [_items objectAtIndex:indexPath.row];
}

回答1:

At the time when you set the value of the UILabel, the view has not yet been loaded, so if you check in debug, you'll probably find detailLabel is nil.

Why not pass the value in a custom init method? e.g.

- (id)initWithDetails:(NSString *)detailsText;

Then in viewDidLoad, assign the value?

According to your edit, in answer to your question as to why it is working:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    TestViewController *test = [[testViewController alloc] init];

    NSLog(@"Before: %@", test.label);

    if(test.view){}

    NSLog(@"After: %@", test.label);

    [[test label] setText:@"My Test"];

    [self.navigationController pushViewController:test animated:YES];
}

I have mocked up your scenario, if you access 'view' on a ViewController, it will call viewDidLoad if the view does not exist. So your UILabel now becomes set. Here is the output from the console.

2013-10-11 16:21:04.555 test[87625:11303] Before: (null)
2013-10-11 16:21:04.559 test[87625:11303] After: <UILabel: 0x75736b0; frame = (148 157; 42 21); text = 'Label'; clipsToBounds = YES; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <CALayer: 0x7573740>>

I recommend using a custom init method, rather than this approach - this above example is a hack. Use something like this E.g.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    testViewController *test = [[testViewController alloc] initWithText:@"My Test"];

    [self.navigationController pushViewController:test animated:YES];
}

If you do not wish to use a custom initialiser, I suggest a public property on your DetailViewController of type NSString. Assign that using your approach after init is called. Then within DetailViewController, in viewDidLoad, or appear, set the IBOutlet to the value of the property containing the NSString.



回答2:

Its not getting updated because you are making writing @property (weak, nonatomic) IBOutlet UILabel *detailLabel; You are making the UILabel as weak property. You must make it strong property. @property (strong, nonatomic) IBOutlet UILabel *detailLabel; As you are making your property weak so its getting destroyed.

To know more about weak and strong propertied you can refer Differences between strong and weak in Objective-C