关于uitableview:tableView didSelectRowAtIndexPath在iOS 7上无法正常工作。为什么?

tableView didSelectRowAtIndexPath doesn't work properly on iOS 7. Why?

首先,我想说的是,我只想提出这个问题,因为我想了解正在发生的事情。

我在Xcode5的新安装中打开了一个旧的Xcode项目(非常简单)。当我意识到它在iOS 7上不起作用时。为什么?不知道。。

我看到了一些其他的问题,没有得到任何有用的答案,所以我做了一个简单的测试。在UITableViewController中,除didSelectRowAtIndexPath上的工程外,所有工程均正常。

过来看

rootview控制器.h:

1
2
3
4
@interface RootViewController : UITableViewController

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

根视图控制器.m在viewdidload中,我初始化数组(使用一些字符串)。

实现数据源和委托方法(是的,我将委托和数据源设置为TableView)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
- (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;
}

问题在于:

1
2
3
4
5
6
7
8
9
10
11
    - (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是一个简单的uiviewController:

(是的,我在NIB文件上设置了IBoutlet)

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

@end

问题是这在iOS7上不起作用,DetailViewController中的标签没有更新。我试着在pushViewController前后设置标签文本。

这适用于所有以前版本的iOS。

为什么不在iOS 7上工作??

唯一的方法就是,像我在另一个问题上看到的那样:

1
2
3
4
5
6
7
8
9
10
11
12
13
- (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];
    });
}

有人能帮我弄明白这是怎么回事吗??

谢谢!

γ

编辑

它也可以这样工作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
- (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];
}


设置uilabel值时,视图尚未加载,因此如果签入debug,可能会发现detaillabel为零。

为什么不在自定义init方法中传递该值?例如

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

然后在VIEWDIDLOAD中,指定值?

根据你的编辑,回答你的问题,为什么它是有效的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
- (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];
}

我已经模拟了你的场景,如果你在一个视图控制器上访问"视图",如果视图不存在,它将调用viewdidload。所以你的uilabel现在已经设置好了。这是控制台的输出。

1
2
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>>

我建议使用自定义的init方法,而不是这种方法-上面的例子是一个hack。使用类似的东西,例如

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

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

如果您不想使用自定义初始化器,我建议在nsstring类型的detailview控制器上使用公共属性。在调用init之后使用您的方法分配它。然后在detailview控制器中,在viewdidload或appear中,将iboutlet设置为包含nsstring的属性的值。


因为你在写作,所以它没有更新。@属性(弱,非原子)IBoutlet UILabel*detailLabel;您正在将uilabel设置为弱属性。你必须使它具有强大的属性。@属性(强,非原子)IBoutlet UILabel*detailLabel;因为你让你的财产变得脆弱,所以它会被摧毁。

要了解更多关于弱和强属性的信息,可以参考目标C强与弱的区别