UITableView问题,当使用单独的委托/数据源

一般说明:

要开始工作,我有一个UITableView已被放置到使用Interface Builder的Xcode生成的视图。 视图的文件所有者被设置为UIViewController的Xcode生成的子类。 在这个子类中,我添加了numberOfSectionsInTableView: tableView:numberOfRowsInSection:工作实现numberOfSectionsInTableView: tableView:numberOfRowsInSection:tableView:cellForRowAtIndexPath:dataSourcedelegate通过Interface Builder中的File Owner连接到这个类。

以上configuration没有问题。 当我想把这个Table View的dataSourcedelegate -implementations移出到一个单独的类时,就会出现这个问题,很可能是因为除了Table View之外,View上还有其他控件,我想移动Table View相关的代码到自己的class级。 要做到这一点,我尝试以下几点:

  • 在Xcode中创build一个新的UITableViewController子类
  • numberOfSectionsInTableView:tableView:numberOfRowsInSection:tableView:cellForRowAtIndexPath:的已知好的实现移动到新的子类
  • UITableViewController拖到InterfaceBuilder中现有 XIB的顶层,删除为此UITableViewController自动创build的UIView / UITableViewController ,然后设置UITableViewController的类以匹配新的子类
  • 删除以前工作的UITableView的现有dataSourcedelegate连接,并将它们连接到新的UITableViewController

完成后,我没有工作的UITableView 。 我最终得出了三个结果中的一个,这些结果可能是随机发生的:

  • UITableView加载时,我得到一个运行时错误,指示我正在发送tableView:cellForRowAtIndexPath:一个对象,它不能识别它
  • UITableView加载时,项目没有错误地进入debugging器
  • 没有错误,但UITableView没有出现

通过一些debugging和创build一个基本的项目来重现这个问题,我通常看到上面的第三个选项(没有错误,但没有可见的表视图)。 我添加了一些NSLog调用,发现虽然numberOfSectionsInTableView:numberOfRowsInSection:都被调用, cellForRowAtIndexPath:不是。 我相信我错过了一些非常简单的东西,希望对于那些比我有更多经验的人来说,答案可能是显而易见的。 如果这不是一个简单的答案,我会很乐意更新一些代码或一个示例项目。 谢谢你的时间!

完整的步骤来重现:

  • 在Xcode中创build一个新的iPhone OS,基于视图的应用程序,并将其TableTest
  • 在Interface Builder中打开TableTestViewController.xib并将UITableView拖到提供的视图表面上。
  • UITableViewdataSourcedelegate -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删除dataSourcedelegate绑定,并将相同的两个绑定重新连接到我们创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了这个项目,并遇到了同样的问题。 基本上你几乎在那里。 有两件事缺失(一旦修复它的作品):

  • 您需要将TableTestTableViewControllertableView连接到屏幕上的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下添加其他UILabelsUIImages ,并在它们之下或之上显示UITableView

我只花了好几个小时拉我的头发,试图找出为什么UITableView不会出现,当我把它embedded在一个单独的笔尖,而不是在主要的笔尖。 我终于find了上面的讨论,并意识到这是因为我的UITableViewController没有被保留! 显然UITableView的委托和数据源属性没有标记为“保留”,所以我的笔尖加载,但控制器被扔了…由于奇迹objective-c我没有得到任何错误信息… …我仍然不明白为什么它没有崩溃。 我知道我以前见过“发送给xxx的消息”,为什么不给我一个呢?!

我认为大多数开发人员会认为,他们在界面构build器中构build的结构将被放在更大的环境中(Nib),而不会被释放。 我想我知道他们为什么要这样做,这样iPhone就可以在内存不足的情况下丢弃和重新加载笔尖的一部分。 但是,那个人很难搞清楚。

有人可以告诉我,我应该在文档中看到这种行为吗?

另外 – 关于连接视图。 首先,如果从UI构build器中拖入一个,您将看到它们将视图属性(这是一个IBOutlet )连接到表视图。 没有必要暴露tableView ,似乎在内部设置。 事实上,除非你想要viewDidLoad通知,否则似乎没有必要设置视图。 我只是打破了我的uitableviewuitableviewcontroller (只有委托和数据源设置)之间的视图连接,它显然工作正常。

是的,由于某种原因(如果有人知道为什么请chim)… UITableViewController tableView属性不作为IBOutlet公开,即使它是一个公共属性。 所以当你使用Interface Builder时,你不能看到连接到你的其他UITableView属性。 所以在你的子类中,你可以创build一个标记为IBOutlettableView属性并连接它。

这一切似乎hacky和解决方法,但它似乎是唯一的方式来分离UITableViewController's UITableView并把它放在UI层次结构中的其他地方。 我遇到了同样的问题,当我试图devise视图,除了UITableView东西,这是我解决它的方式…这是正确的做法?

我能够做到这一点。 我用4个TableViews和一个带有video的webview构build了一个非常好的仪表板。 关键是将单独的tableView控制器和IBOutlets分配给视图控制器中定义的其他tableview控制器。 在UIB中,只需要将其他tableview控制器连接到视图控制器的文件所有者。 然后将表连接到数据源和委托的相应视图控制器。