tableView didSelectRowAtIndexPath doesn't work properly on iOS 7. Why?
首先,我想说的是,我只想提出这个问题,因为我想了解正在发生的事情。
我在Xcode5的新安装中打开了一个旧的Xcode项目(非常简单)。当我意识到它在iOS 7上不起作用时。为什么?不知道。。
我看到了一些其他的问题,没有得到任何有用的答案,所以我做了一个简单的测试。在
过来看
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]; } |
(是的,我在NIB文件上设置了IBoutlet)
1 2 3 4 | @interface DetailViewController : UIViewController @property (weak, nonatomic) IBOutlet UILabel *detailLabel; @end |
问题是这在iOS7上不起作用,
这适用于所有以前版本的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强与弱的区别