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中强弱的区别