UITableView问题,当使用单独的委托/数据源
一般说明:
要开始工作,我有一个UITableView已被放置到使用Interface Builder的Xcode生成的视图。 视图的文件所有者被设置为UIViewController的Xcode生成的子类。 在这个子类中,我添加了numberOfSectionsInTableView: tableView:numberOfRowsInSection:工作实现numberOfSectionsInTableView: tableView:numberOfRowsInSection:和tableView:cellForRowAtIndexPath:的dataSource和delegate通过Interface Builder中的File Owner连接到这个类。
以上configuration没有问题。 当我想把这个Table View的dataSource和delegate -implementations移出到一个单独的类时,就会出现这个问题,很可能是因为除了Table View之外,View上还有其他控件,我想移动Table View相关的代码到自己的class级。 要做到这一点,我尝试以下几点:
- 在Xcode中创build一个新的
UITableViewController子类 - 将
numberOfSectionsInTableView:,tableView:numberOfRowsInSection:和tableView:cellForRowAtIndexPath:的已知好的实现移动到新的子类 - 将
UITableViewController拖到InterfaceBuilder中现有 XIB的顶层,删除为此UITableViewController自动创build的UIView/UITableViewController,然后设置UITableViewController的类以匹配新的子类 - 删除以前工作的
UITableView的现有dataSource和delegate连接,并将它们连接到新的UITableViewController
完成后,我没有工作的UITableView 。 我最终得出了三个结果中的一个,这些结果可能是随机发生的:
- 当
UITableView加载时,我得到一个运行时错误,指示我正在发送tableView:cellForRowAtIndexPath:一个对象,它不能识别它 - 当
UITableView加载时,项目没有错误地进入debugging器 - 没有错误,但
UITableView没有出现
通过一些debugging和创build一个基本的项目来重现这个问题,我通常看到上面的第三个选项(没有错误,但没有可见的表视图)。 我添加了一些NSLog调用,发现虽然numberOfSectionsInTableView:和numberOfRowsInSection:都被调用, cellForRowAtIndexPath:不是。 我相信我错过了一些非常简单的东西,希望对于那些比我有更多经验的人来说,答案可能是显而易见的。 如果这不是一个简单的答案,我会很乐意更新一些代码或一个示例项目。 谢谢你的时间!
完整的步骤来重现:
- 在Xcode中创build一个新的iPhone OS,基于视图的应用程序,并将其
TableTest - 在Interface Builder中打开
TableTestViewController.xib并将UITableView拖到提供的视图表面上。 - 将
UITableView的dataSource和delegate-outlets连接到File的Owner,它应该已经代表了TableTestViewController类。 保存您的更改 - 回到Xcode,将下面的代码添加到
TableTestViewController.m:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { NSLog(@"Returning num sections"); return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { NSLog(@"Returning num rows"); return 1; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { NSLog(@"Trying to return cell"); static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease]; } cell.text = @"Hello"; NSLog(@"Returning cell"); return cell; }
-
build立和去,你应该看到你的字出现在
UITableView -
现在试图将这个
UITableView的逻辑移出到一个单独的类中,首先在Xcode中创build一个新文件,selectUITableViewController子类并调用类TableTestTableViewController - 从
TableTestViewController.m删除上面的代码片段,并将其放置到TableTestTableViewController.m,用我们的replace这三个方法的默认实现。 - 回到界面生成器在同一个
TableTestViewController.xib文件,拖动一个UITableViewController到主IB窗口,并删除自动附带的新的UITableView对象 - 将这个新的
UITableViewController的类设置为TableTestTableViewController - 从现有的以前工作的
UITableView删除dataSource和delegate绑定,并将相同的两个绑定重新连接到我们创build的新TableTestTableViewController。 - 保存更改,生成和去,如果你正在得到我得到的结果,请注意
UITableView不再正常工作
解决scheme:通过一些更多的疑难解答和iPhone开发者论坛的一些帮助,我已经logging了一个解决scheme! 项目的主要UIViewController子类需要一个指向UITableViewController实例的出口。 要做到这一点,只需将以下内容添加到主视图的标题( TableTestViewController.h )中:
#import "TableTestTableViewController.h"
和
IBOutlet TableTestTableViewController *myTableViewController;
然后,在Interface Builder中,将主窗口中文件所有者的新出口连接到TableTestTableViewController 。 在XIB的UI部分中不需要更改。 只要有这个sockets,即使没有用户代码直接使用它,完全解决了这个问题。 感谢那些帮助和信誉在iPhone开发者论坛find解决scheme的BaldEagle。
我跟着你的步骤,重新创build了这个项目,并遇到了同样的问题。 基本上你几乎在那里。 有两件事缺失(一旦修复它的作品):
-
您需要将
TableTestTableViewController的tableView连接到屏幕上的UITableView。 正如我之前所说,因为它不是IBOutlet你可以覆盖tableView属性,使它和IBOutlet:@interface TableTestTableViewController : UITableViewController { UITableView *tableView; } @property (nonatomic, retain) IBOutlet UITableView *tableView; -
接下来是添加对
TableTestTableViewController的引用,并将其保留在TableTestViewController。 否则,你的TableTestTableViewController可能会被释放(加载后,没有任何挂在它的笔尖),这就是为什么你看到不稳定的结果,崩溃或没有显示。 要做到这一点,添加:@interface TableTestViewController : UIViewController { TableTestTableViewController *tableViewController; } @property (nonatomic, retain) IBOutlet TableTestTableViewController *tableViewController;并在Interface Builder中将其连接到
TableTestTableViewController实例。
以上这在我的机器上工作得很好。
此外,我认为这将是很好的陈述所有这一切的动机(而不是仅仅使用UITableViewController自己的UITableView )。 在我的情况下是使用其他视图,只是在相同的屏幕上的内容的UITableView 。 所以我可以在UIView下添加其他UILabels或UIImages ,并在它们之下或之上显示UITableView 。
我只花了好几个小时拉我的头发,试图找出为什么UITableView不会出现,当我把它embedded在一个单独的笔尖,而不是在主要的笔尖。 我终于find了上面的讨论,并意识到这是因为我的UITableViewController没有被保留! 显然UITableView的委托和数据源属性没有标记为“保留”,所以我的笔尖加载,但控制器被扔了…由于奇迹objective-c我没有得到任何错误信息… …我仍然不明白为什么它没有崩溃。 我知道我以前见过“发送给xxx的消息”,为什么不给我一个呢?!
我认为大多数开发人员会认为,他们在界面构build器中构build的结构将被放在更大的环境中(Nib),而不会被释放。 我想我知道他们为什么要这样做,这样iPhone就可以在内存不足的情况下丢弃和重新加载笔尖的一部分。 但是,那个人很难搞清楚。
有人可以告诉我,我应该在文档中看到这种行为吗?
另外 – 关于连接视图。 首先,如果从UI构build器中拖入一个,您将看到它们将视图属性(这是一个IBOutlet )连接到表视图。 没有必要暴露tableView ,似乎在内部设置。 事实上,除非你想要viewDidLoad通知,否则似乎没有必要设置视图。 我只是打破了我的uitableview和uitableviewcontroller (只有委托和数据源设置)之间的视图连接,它显然工作正常。
是的,由于某种原因(如果有人知道为什么请chim)… UITableViewController tableView属性不作为IBOutlet公开,即使它是一个公共属性。 所以当你使用Interface Builder时,你不能看到连接到你的其他UITableView属性。 所以在你的子类中,你可以创build一个标记为IBOutlet的tableView属性并连接它。
这一切似乎hacky和解决方法,但它似乎是唯一的方式来分离UITableViewController's UITableView并把它放在UI层次结构中的其他地方。 我遇到了同样的问题,当我试图devise视图,除了UITableView东西,这是我解决它的方式…这是正确的做法?
我能够做到这一点。 我用4个TableViews和一个带有video的webview构build了一个非常好的仪表板。 关键是将单独的tableView控制器和IBOutlets分配给视图控制器中定义的其他tableview控制器。 在UIB中,只需要将其他tableview控制器连接到视图控制器的文件所有者。 然后将表连接到数据源和委托的相应视图控制器。