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

首先,我想说我只是提出这个问题,因为我想了解发生了什么。

我在Xcode5上全新安装了一个旧的Xcode项目(一个非常简单的项目)。 当我意识到它不适用于iOS 7.为什么? 不知道..

我看到其他一些问题,没有得到任何有用的答案,所以我做了一个简单的testing。 在UITableViewController除了didSelectRowAtIndexPath之外,所有工作都正常

一探究竟

RootViewController.h:

 @interface RootViewController : UITableViewController @property (strong, nonatomic) NSMutableArray *items; @end 

RootViewController.m在viewDidLoad我初始化数组(有一些string)。

实现dataSource和委托方法(是的,我把委托和数据源设置为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; } 

问题在这里:

  - (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:

(是的,我将IBOutlet设置为nib文件)

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

问题是,这不适用于iOS7, DetailViewController中的标签不会更新。 我尝试在pushViewController之前和之后设置标签文本。

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

为什么不在iOS 7上工作?

我得到这个工作的唯一方法就像我在另一个问题上看到的那样:

 - (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]; }); } 

有人可以帮我理解这里发生了什么?

谢谢!

_

编辑

它也是这样工作的:

 - (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方法中的值? 例如

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

然后在viewDidLoad中,赋值?

根据你的编辑,回答你的问题,为什么它的工作:

 - (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]; } 

我嘲笑了你的场景,如果你访问ViewController的“视图”,如果视图不存在,它将调用viewDidLoad。 所以你的UILabel现在成为了设置。 这是控制台的输出。

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

我build议使用自定义的init方法,而不是这种方法 – 上面的例子是一个黑客。 使用像这样的东西

 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { testViewController *test = [[testViewController alloc] initWithText:@"My Test"]; [self.navigationController pushViewController:test animated:YES]; } 

如果你不想使用自定义的初始化程序,我build议你的DetailViewControllertypes为NSString的公共属性。 在调用init之后指定使用你的方法。 然后在DetailViewController中,在viewDidLoad中,或者出现,将IBOutlet设置为包含NSString的属性的值。

它没有得到更新,因为你正在写@property(弱,非primefaces)IBOutlet UILabel * detailLabel; 你正在使UILabel成为弱财产。 你必须使它强大的财产。 @属性(强,非primefaces)IBOutlet UILabel * detailLabel; 因为你正在使你的财产变弱,所以它被破坏了。

要了解更多有关弱势和强势资产的信息,可以参考Objective-C中强弱的区别