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控制器连接到视图控制器的文件所有者。 然后将表连接到数据源和委托的相应视图控制器。