54

一般说明:

首先,我有一个UITableView使用 Interface Builder 放置在 Xcode 生成的视图上的内容。视图的文件所有者设置为 Xcode 生成的UIViewController. 在这个子类中,我添加了和表视图的工作实现,并通过numberOfSectionsInTableView: tableView:numberOfRowsInSection:接口生成器中的文件所有者连接到这个类。tableView:cellForRowAtIndexPath:dataSourcedelegate

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

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

完成后,我没有工作UITableView. 我最终得到了三个看似随机发生的结果之一:

  • 加载时UITableView,我收到一个运行时错误,表明我正在发送tableView:cellForRowAtIndexPath:到一个无法识别它的对象
  • 加载时UITableView,项目无错误地进入调试器
  • 没有错误,但UITableView没有出现

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

完整的重现步骤:

  • 在 Xcode 中创建一个新的 iPhone OS,基于视图的应用程序并调用它TableTest
  • TableTestViewController.xib在 Interface Builder 中打开并将 aUITableView拖到提供的视图表面上。
  • UITableView'sdataSourcedelegate-outlets 连接到应该已经代表TableTestViewController-class 的 File's Owner。保存您的更改
  • 回到 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 and Go,你应该会看到这个词Hello出现在UITableView

  • 现在尝试将 thisUITableView的逻辑移到一个单独的类中,首先在 Xcode 中创建一个新文件,选择UITableViewController子类并调用该类TableTestTableViewController

  • 把上面的代码片段去掉,TableTestViewController.m放到 里面TableTestTableViewController.m,把这三个方法的默认实现替换成我们的。
  • 返回同一文件中的 Interface Builder TableTestViewController.xib,将 aUITableViewController拖入主 IB 窗口并删除UITableView自动附带的新对象
  • 将这个新的类设置UITableViewControllerTableTestTableViewController
  • 从现有的、先前工作的中删除dataSource和绑定,然后将相同的两个绑定重新连接到我们创建的新绑定。delegateUITableViewTableTestTableViewController
  • 保存更改,构建并开始,如果你得到我得到的结果,请注意UITableView不再正常运行

解决方案: 通过更多故障排除和来自iPhone 开发者论坛的帮助,我记录了一个解决方案!项目的主要UIViewController子类需要一个指向UITableViewController实例的出口。为此,只需将以下内容添加到主视图的标题 ( TableTestViewController.h) 中:

#import "TableTestTableViewController.h"

IBOutlet TableTestTableViewController *myTableViewController;

然后,在 Interface Builder 中,将 File's Owner 的新出口连接到TableTestTableViewController主 IB 窗口中。XIB 的 UI 部分无需更改。只需设置此插座,即使没有用户代码直接使用它,也可以完全解决问题。感谢那些帮助并感谢 iPhone 开发者论坛上的 BaldEagle 找到解决方案的人。

4

4 回答 4

23

我按照您的步骤,重新创建了项目并遇到了同样的问题。基本上你就快到了。缺少两件事(一旦修复它就可以了):

  • 您需要将 的 连接tableViewTableTestTableViewController屏幕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实例。

有了上述内容,这在我的机器上运行良好。

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

于 2008-11-01T18:03:18.370 回答
4

我只是花了很多时间把头发拉出来,试图弄清楚为什么UITableView当我将它嵌入单独的笔尖而不是主笔尖时不会出现。我终于在上面找到了你的讨论,并意识到这是因为我UITableViewController的没有被保留!显然,委托和数据源属性UITableView没有标记为“保留”,所以我的笔尖正在加载,但控制器被扔掉了......由于objective-c的奇迹,我根本没有收到任何错误消息......我仍然不明白为什么它没有崩溃。我知道我以前看过“发送给已发布 xxx 的消息”……为什么它不给我其中之一?!?

我认为大多数开发人员会假设他们在界面构建器中构建的结构将保存在更大的上下文(Nib)中,并且不会发布。我想我知道他们为什么这样做……这样 iPhone 就可以在内存不足的情况下放下并重新加载笔尖的一部分。但是,伙计,这很难弄清楚。

有人能告诉我应该在哪里阅读文档中的这种行为吗?

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

于 2009-03-07T04:43:34.103 回答
3

是的,出于某种原因(如果有人知道原因,请插话......)即使它是公共财产,它的财产也没有tableView公开UITableViewControllerIBOutlet因此,当您使用 Interface Builder 时,您看不到该属性以连接到您的其他UITableView. 因此,在您的子类中,您可以创建一个tableView标记为 an 的属性IBOutlet并将其连接起来。

这一切对我来说似乎很老套,也是一种解决方法,但它似乎是分离 aUITableViewController's UITableView并将其放在 UI 层次结构中的其他位置的唯一方法。当我尝试设计视图时遇到了同样的问题,UITableView而这就是我解决它的方式......这是正确的方法吗???

于 2008-10-31T20:16:48.257 回答
2

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

于 2012-03-10T23:03:13.487 回答