使用单独的委托/数据源时的 UITableView 问题 [英] UITableView issue when using separate delegate/dataSource

查看:21
本文介绍了使用单独的委托/数据源时的 UITableView 问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

一般说明:

从什么工作开始,我有一个 UITableView,它已使用 Interface Builder 放置在 Xcode 生成的视图上.视图的文件所有者设置为 Xcode 生成的 UIViewController 子类.对于这个子类,我添加了 numberOfSectionsInTableView: tableView:numberOfRowsInSection:tableView:cellForRowAtIndexPath: 和表视图的 dataSource 的工作实现委托通过Interface Builder中的File Owner连接到这个类.

To start with what works, I have a UITableView which has been placed onto an Xcode-generated view using Interface Builder. The view's File Owner is set to an Xcode-generated subclass of UIViewController. To this subclass I have added working implementations of numberOfSectionsInTableView: tableView:numberOfRowsInSection: and tableView:cellForRowAtIndexPath: and the Table View's dataSource and delegate are connected to this class via the File Owner in Interface Builder.

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

The above configuration works with no problems. The issue occurs when I want to move this Table View's dataSource and delegate-implementations out to a separate class, most likely because there are other controls on the View besides the Table View and I'd like to move the Table View-related code out to its own class. To accomplish this, I try the following:

  • 在Xcode中新建一个UITableViewController的子类
  • numberOfSectionsInTableView:tableView:numberOfRowsInSection:tableView:cellForRowAtIndexPath: 的已知良好实现移动到新的子类
  • 将一个UITableViewController拖到InterfaceBuilder中现有XIB的顶层,删除UIView/UITableView为这个 UITableViewController 自动创建,然后设置 UITableViewController 的类以匹配新的子类
  • 移除之前工作的 UITableView 现有的 dataSourcedelegate 连接,并将它们连接到新的 UITableViewController>
  • Create a new subclass of UITableViewController in Xcode
  • Move the known-good implementations of numberOfSectionsInTableView:, tableView:numberOfRowsInSection: and tableView:cellForRowAtIndexPath: to the new subclass
  • Drag a UITableViewController to the top level of the existing XIB in InterfaceBuilder, delete the UIView/UITableView that are automatically created for this UITableViewController, then set the UITableViewController's class to match the new subclass
  • Remove the previously-working UITableView's existing dataSource and delegate connections and connect them to the new UITableViewController

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

When complete, I do not have a working UITableView. I end up with one of three outcomes which can seemingly happen at random:

  • UITableView 加载时,我收到一个运行时错误,表明我正在将 tableView:cellForRowAtIndexPath: 发送到无法识别它的对象
  • UITableView加载时,项目进入调试器没有错误
  • 没有错误,但是UITableView没有出现
  • When the UITableView loads, I get a runtime error indicating I am sending tableView:cellForRowAtIndexPath: to an object which does not recognize it
  • When the UITableView loads, the project breaks into the debugger without error
  • There is no error, but the UITableView does not appear

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

With some debugging and having created a basic project just to reproduce this issue, I am usually seeing the 3rd option above (no error but no visible table view). I added some NSLog calls and found that although numberOfSectionsInTableView: and numberOfRowsInSection: are both getting called, cellForRowAtIndexPath: is not. I am convinced I'm missing something really simple and was hoping the answer may be obvious to someone with more experience than I have. If this doesn't turn out to be an easy answer I would be happy to update with some code or a sample project. Thanks for your time!

完整的重现步骤:

  • 在 Xcode 中创建一个新的 iPhone 操作系统,基于视图的应用程序并调用它TableTest
  • 在 Interface Builder 中打开 TableTestViewController.xib 并将 UITableView 拖到提供的视图表面上.
  • UITableViewdataSourcedelegate-outlets 连接到 File's Owner,它应该已经代表了 TableTestViewController-类.保存您的更改
  • 返回 Xcode,将以下代码添加到 TableTestViewController.m:
  • Create a new iPhone OS, View-Based Application in Xcode and call it TableTest
  • Open TableTestViewController.xib in Interface Builder and drag a UITableView onto the provided view surface.
  • Connect the UITableView's dataSource and delegate-outlets to File's Owner, which should already represent the TableTestViewController-class. Save your changes
  • Back in Xcode, add the following code to 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

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

    Now to attempt to move this UITableView's logic out to a separate class, first create a new file in Xcode, choosing UITableViewController subclass and calling the class TableTestTableViewController

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

    Solution: With some more troubleshooting and some assistance from the iPhone Developer Forums, I've documented a solution! The main UIViewController subclass of the project needs an outlet pointing to the UITableViewController instance. To accomplish this, simply add the following to the primary view's header (TableTestViewController.h):

    #import "TableTestTableViewController.h"
    

    IBOutlet TableTestTableViewController *myTableViewController;
    

    然后,在 Interface Builder 中,将 File's Owner 的新插座连接到主 IB 窗口中的 TableTestTableViewController.XIB 的 UI 部分不需要更改.即使没有用户代码直接使用它,只需将这个插座放在适当的位置,就可以完全解决问题.感谢提供帮助的人,感谢 iPhone 开发者论坛上的 BaldEagle 找到了解决方案.

    Then, in Interface Builder, connect the new outlet from File's Owner to TableTestTableViewController in the main IB window. No changes are necessary in the UI part of the XIB. Simply having this outlet in place, even though no user code directly uses it, resolves the problem completely. Thanks to those who've helped and credit goes to BaldEagle on the iPhone Developer Forums for finding the solution.

    推荐答案

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

    I followed your steps, recreated the project and ran into the same problem. Basically you are almost there. There are 2 things missing (once fixed it works):

    • 您需要将 TableTestTableViewControllertableView 连接到屏幕上的 UITableView.正如我之前所说,因为它不是 IBOutlet,您可以覆盖 tableView 属性并使其成为 IBOutlet:

    • You need to connect the tableView of the TableTestTableViewController to the UITableView you have on the screen. As I said before because it is not IBOutlet you can override the tableView property and make it and IBOutlet:

    @interface TableTestTableViewController : UITableViewController {
        UITableView *tableView;
    }
    
    @property (nonatomic, retain) IBOutlet UITableView *tableView;
    

  • 接下来是添加对TableTestTableViewController 的引用并将其保留在TableTestViewController 中.否则您的 TableTestTableViewController 可能会被释放(在加载笔尖后没有任何东西挂在上面.)这就是为什么您会看到不稳定的结果、崩溃或没有任何显示.要做到这一点,请添加:

  • Next thing is to add a reference to the TableTestTableViewController and retain it in the TableTestViewController. Otherwise your TableTestTableViewController may be released (after loading the nib with nothing hanging on to it.) and that is why you are seeing the erratic results, crashes or nothing showing. To do that add:

    @interface TableTestViewController : UIViewController {
        TableTestTableViewController *tableViewController;
    }
    
    @property (nonatomic, retain) IBOutlet TableTestTableViewController  *tableViewController;
    

    并将其在 Interface Builder 中连接到 TableTestTableViewController 实例.

    and connect that in the Interface Builder to the TableTestTableViewController instance.

    使用上述方法,这在我的机器上运行良好.

    With the above this worked fine on my machine.

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

    Also I think it would be good to state the motivation behind all this (instead of just using the UITableViewController with its own UITableView). In my case it was to use other views that just the UITableView on the same screenful of content. So I can add other UILabels or UIImages under UIView and show the UITableView under them or above them.

    这篇关于使用单独的委托/数据源时的 UITableView 问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆