使用单独的delegate / dataSource时的UITableView问题 [英] UITableView issue when using separate delegate/dataSource

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

问题描述

一般说明:



为了开始使用,我有一个 UITableView 已使用Interface Builder放置在Xcode生成的视图上。视图的文件所有者设置为Xcode生成的 UIViewController 子类。对于这个子类,我已经添加了 numberOfSectionsInTableView:tableView:numberOfRowsInSection: tableView:cellForRowAtIndexPath: dataSource 委托通过Interface Builder中的文件所有者连接到此类。



上面的配置没有问题。当我想将此表视图的 dataSource 委托 - 实现移动到单独的类时,会出现此问题,很可能因为除了表视图之外,View上还有其他控件,我想将与Table View相关的代码移动到自己的类中。要实现这个,我尝试以下:




  • 创建 UITableViewController 在Xcode中

  • 移动 numberOfSectionsInTableView:的已知良好实现tableView:numberOfRowsInSection: c>到新子类

  • 拖动 UITableViewController / code>到InterfaceBuilder中现有 XIB的顶层,删除 UIView / UITableView 自动创建的 UITableViewController ,然后设置 UITableViewController 的类匹配新的子类

  • 删除以前工作的 UITableView 的现有 dataSource code>委托连接并将它们连接到新 UITableViewController



完成后,我没有工作 UITableView 。我最终得到三个结果之一,它们似乎随机发生:




  • UITableView 载入,我得到一个运行时错误,指示我发送 tableView:cellForRowAtIndexPath:到一个不能识别它的对象

  • UITableView 加载时,项目会打断到调试器没有错误

  • 没有错误,但是 UITableView 不出现



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



完成以下步骤:




  • 在Xcode中创建一个新的iPhone操作系统,基于视图的应用程序并调用 TableTest

  • 打开 TableTestViewController.xib ,并将 UITableView 拖到所提供的视图表面。

  • UITableView dataSource 委托 ,它应该已经代表 TableTestViewController -class。保存更改

  • 返回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;
      }




      • 应该会在 UITableView


      • 中出现 Hello

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


      • TableTestViewController.m ,并将它放入 TableTestTableViewController.m ,用我们的方法替换这三个方法的默认实现。

      • 在同一个 TableTestViewController.xib -file中的Interface Builder中,将 UITableViewController 拖到主IB窗口并删除自动附带的 UITableView 对象

      • 为此新 UITableViewController TableTestTableViewController

      • 删除 dataSource code> UITableView 中的code> delegate 绑定,并重新连接相同的两个绑定到新的

      • 保存更改,Build和Go,如果您获得的结果,请注意 UITableView 无法正常运作



      解决方案:更多疑难解答和来自 iPhone开发者论坛的帮助,我已经记录了一个解决方案!项目的主要 UIViewController 子类需要一个指向 UITableViewController 实例的插座。要完成此操作,只需将以下内容添加到主视图的标题( TableTestViewController.h ):

        #importTableTestTableViewController.h

        IBOutlet TableTestTableViewController * myTableViewController; 

      然后,在Interface Builder中,将File's Owner的新插件连接到 TableTestTableViewController 。在XIB的UI部分中不需要进行更改。只要有这个插座,即使没有用户代码直接使用它,完全解决问题。感谢那些在iPhone开发者论坛上帮助和信任BaldEagle的人,寻找解决方案。

      解决方案

      步骤,重新创建项目并遇到同样的问题。基本上你几乎在那里。有两个缺失的东西(一旦固定它工作):




      • 您需要连接 tableView 到您在屏幕上的 UITableView 中的 TableTestTableViewController 正如我之前说的,因为它不是 IBOutlet ,您可以覆盖 tableView 属性,并使它和 IBOutlet

          @interface TableTestTableViewController:UITableViewController {
        UITableView * tableView;
        }

        @property(nonatomic,retain)IBOutlet UITableView * tableView;接下来的事情是添加一个对 TableTestTableViewController

        的引用 code>并保留在 TableTestViewController 中。否则你的 TableTestTableViewController 可能会被释放(在加载nib后没有挂上它。)这就是为什么你看到不稳定的结果,崩溃或没有显示。添加:

          @interface TableTestViewController:UIViewController {
        TableTestTableViewController * tableViewController;
        }

        @property(nonatomic,retain)IBOutlet TableTestTableViewController * tableViewController;

        并在Interface Builder中将它连接到 TableTestTableViewController




      使用上面的方法在我的机器上工作得很好。



      另外,我认为这将是很好的陈述所有这一切的动机(而不是只使用 UITableViewController 它自己的 UITableView )。在我的情况下,它是使用其他视图只是 UITableView 在同一屏幕的内容。所以我可以在 UIView 下添加其他 UILabels UIImages 显示它们下面的 UITableView


      General Description:

      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.

      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:

      • 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

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

      • 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

      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!

      Complete steps to reproduce:

      • 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, and you should see the word Hello appear in the UITableView

      • 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

      • Remove the above code snippet from TableTestViewController.m and place it into TableTestTableViewController.m, replacing the default implementation of these three methods with ours.
      • Back in Interface Builder within the same TableTestViewController.xib-file, drag a UITableViewController into the main IB window and delete the new UITableView object that automatically came with it
      • Set the class for this new UITableViewController to TableTestTableViewController
      • Remove the dataSource and delegate bindings from the existing, previously-working UITableView and reconnect the same two bindings to the new TableTestTableViewController we created.
      • Save changes, Build and Go, and if you're getting the results I'm getting, note the UITableView no longer functions properly

      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"
      

      and

      IBOutlet TableTestTableViewController *myTableViewController;
      

      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):

      • 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;
        

      • 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;
        

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

      With the above this worked fine on my machine.

      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.

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

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