使用单独的委托/ dataSource时出现UITableView问题

时间:2008-10-31 17:48:41

标签: iphone objective-c cocoa-touch uitableview

一般说明:

首先,我使用Interface Builder将UITableView置于Xcode生成的视图中。视图的文件所有者设置为Xcode生成的UIViewController子类。对于这个子类,我添加了numberOfSectionsInTableView: tableView:numberOfRowsInSection:tableView:cellForRowAtIndexPath:的工作实现,表视图的dataSourcedelegate通过Interface Builder中的文件所有者连接到此类。

上述配置没有问题。当我想将此表视图的dataSourcedelegate - 实现移动到单独的类时,问题就出现了,很可能是因为除了表视图之外还有View上的其他控件,我想将与表视图相关的代码移到自己的类中。为此,我尝试以下方法:

  • 在Xcode中创建UITableViewController的新子类<​​/ li>
  • 将已知良好的numberOfSectionsInTableView:tableView:numberOfRowsInSection:tableView:cellForRowAtIndexPath:实施方案移至新的子类
  • UITableViewController拖到InterfaceBuilder中现有 XIB的顶层,删除为此{{1}自动创建的UIView / UITableView然后设置UITableViewController的类以匹配新的子类
  • 删除以前工作的UITableViewController现有UITableViewdataSource个关联,并将它们连接到新的delegate

完成后,我没有工作UITableViewController。我最终得出的结果之一似乎是随机发生的:

  • UITableView加载时,我收到运行时错误,指示我将UITableView发送给无法识别它的对象
  • 加载tableView:cellForRowAtIndexPath:时,项目会无错误地进入调试器
  • 没有错误,但UITableView没有出现

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

完成重现的步骤:

  • 在Xcode中创建一个新的iPhone OS,基于视图的应用程序,并将其命名为cellForRowAtIndexPath:
  • 在Interface Builder中打开TableTest,然后将TableTestViewController.xib拖到提供的视图表面上。
  • UITableView的{​​{1}}和UITableView - 个网点连接到文件所有者,该文件的所有者应该已经代表dataSource - 类。保存更改
  • 返回Xcode,将以下代码添加到delegate

TableTestViewController
  • Build and Go,您应该会在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; } 一词
  • 现在尝试将此Hello的逻辑移到单独的类中,首先在Xcode中创建一个新文件,选择UITableView子类并调用类UITableView

  • UITableViewController移除上述代码段并将其放入TableTestTableViewController,将这三种方法的默认实现替换为我们的。
  • 返回同一TableTestViewController.m文件中的Interface Builder,将TableTestTableViewController.m拖到主IB窗口并删除自动附带的新TableTestViewController.xib对象
  • 将此新UITableViewController的班级设置为UITableView
  • 从现有的以前工作UITableViewController中删除TableTestTableViewControllerdataSource绑定,并将相同的两个绑定重新连接到我们创建的新delegate
  • 保存更改,Build and Go,如果您收到我得到的结果,请注意UITableView不再正常运行

解决方案: 通过iPhone Developer Forums的更多故障排除和一些帮助,我记录了一个解决方案!项目的主TableTestTableViewController子类需要一个指向UITableView实例的出口。要完成此操作,只需将以下内容添加到主视图的标题(UIViewController):

UITableViewController

TableTestViewController.h

然后,在Interface Builder中,将文件所有者的新插座连接到主IB窗口中的#import "TableTestTableViewController.h" 。 XIB的UI部分不需要进行任何更改。只需将此插座安装到位,即使没有用户代码直接使用它,也可以完全解决问题。感谢那些在iPhone开发人员论坛上为BaldEagle提供帮助和信誉的人,感谢他们找到解决方案。

4 个答案:

答案 0 :(得分:23)

我按照你的步骤,重新创建了项目并遇到了同样的问题。基本上你几乎就在那里。有两件事缺失(一旦修复就有效):

  • 您需要将tableView的{​​{1}}与屏幕上的TableTestTableViewController相关联。正如我之前所说,因为它不是UITableView,您可以覆盖IBOutlet属性并将其设为tableView

    IBOutlet
  • 接下来要添加对@interface TableTestTableViewController : UITableViewController { UITableView *tableView; } @property (nonatomic, retain) IBOutlet UITableView *tableView; 的引用,并将其保留在TableTestTableViewController中。否则你的TableTestViewController可能会被释放(在加载笔尖后没有任何东西悬挂在它上面)。这就是为什么你看到不稳定的结果,崩溃或什么也没有显示。为此,请添加:

    TableTestTableViewController

    并将Interface Builder中的内容连接到@interface TableTestViewController : UIViewController { TableTestTableViewController *tableViewController; } @property (nonatomic, retain) IBOutlet TableTestTableViewController *tableViewController; 实例。

上面这个在我的机器上工作正常。

此外,我认为最好说明所有这些背后的动机(而不是仅使用TableTestTableViewController使用自己的UITableViewController)。在我的情况下,它是在同一屏幕内容上使用仅UITableView的其他视图。我可以在UITableView下添加其他UILabelsUIImages,并在其下方或上方显示UIView

答案 1 :(得分:5)

我花了好几个小时拉我的头发试图找出为什么UITableView在我将它嵌入一个单独的笔尖而不是主笔尖时不显示的原因。我终于找到了你上面的讨论,并意识到这是因为我的UITableViewController没有被保留!显然UITableView的委托和数据源属性没有标记为“保留”,因此我的笔尖正在加载但是控制器被抛出......由于Objective-c的奇迹,我得到了 no 所有错误消息......我仍然不明白为什么它没有崩溃。我知道我之前看过“发送给发布的xxx的消息”......为什么它不给我一个?!

我认为大多数开发人员会认为他们在界面构建器中构建的结构将保存在更大的上下文(Nib)中,而不会发布。我想我知道他们为什么这样做..所以iPhone可以在低内存中丢弃并重新加载部分笔尖。但男人,这很难搞清楚。

有人可以告诉我应该在文档中阅读有关该行为的内容吗?

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

答案 2 :(得分:3)

出于某种原因是肯定的(如果有人知道原因,请提示...)tableView UITableViewController的{​​{1}}属性不会作为IBOutlet公开,即使它是公共财产。因此,当您使用Interface Builder时,您无法看到该属性连接到您的其他UITableView。因此,在您的子类中,您可以创建标记为tableView的{​​{1}}属性并将其连接起来。

这对我来说似乎很麻烦并且是一种解决方法,但它似乎是将IBOutlet UITableViewController's分开并将其放在UI层次结构中的其他位置的唯一方法。当我试图设计除UITableView以外的东西的视图时,我遇到了同样的问题,这就是我解决它的方式......这是正确的方法吗?

答案 3 :(得分:2)

我能够做到这一点。我构建了一个非常漂亮的仪表板,其中包含4个TableView和带视频的webview。关键是将单独的tableView控制器和IBOutlet用于视图控制器中定义的其他tableview控制器。在UIB中,您只需将其他tableview控制器连接到视图控制器的文件所有者。然后将表连接到数据源和委托的相应视图控制器。