【问题标题】:How can I subclass a UITableView?如何子类化 UITableView?
【发布时间】:2012-02-04 20:11:57
【问题描述】:

我想子类化 UITableView,因为我想在我的应用程序中创建一个可重用的表格视图组件。

我的想法是代替使用委托来表示 cellForRowAtIndexPath,我希望表格视图本身能够获得该调用。

我不认为我想要 UITableViewController,因为我要构建的 UITableView 必须存在于各种 UIViewController 中(这些 UIViewController 可能有自己的 UITableView)。

我将 UITableView 子类化为:

@interface ShareUITableView : UITableView

但没有一个方法被调用。

我的 ShareUITableView 是通过 NIB 通过将自定义类设置为 ShareUITableView 来创建的。我已经在代码中验证了 ShareUITableView 已实例化。

我的 UITableView 没有委托给它的视图控制器,所以这不是问题。

有什么想法吗?

【问题讨论】:

    标签: ios objective-c uitableview cocoa-touch


    【解决方案1】:

    如果我理解你,你需要这个类声明:

    @interface ShareUITableView : UITableView <UITableViewDataSource>
    

    然后,在您的类构造函数中,您应该将实例本身分配为它自己的数据源:

    - (id)init
    {
        //...
        self.dataSource = self;
        //...
    }
    

    当然,类必须采用协议。

    祝你好运!

    【讨论】:

    • 这听起来不错,但我的初始化覆盖没有被调用。正如我所提到的,我似乎有一个 ShareUITableView 实例,因为我可以检查它在视图控制器中的实例是否属于该类型(我将 NIB 中的自定义类设置为 ShareUITableView)。
    • Interface Builder 不会调用 -init。相反,使用 -awakeFromNib: 或 -initWithCoder:
    • 我认为 MVC 的基础会不赞成使用具有自己的数据源和委托方法的 tableView 类。
    【解决方案2】:

    MyTableView.h

    // MyTableView.h
    
    // This overrides the UITableViewDataSource with your own so you can add any methods   you would like.
    @protocol MyTableViewDataSource <UITableViewDataSource>
    
    @required
    // This is where you put methods that are required for your custom table to work (optional)
    - (int)myRequiredMethod;
    
    @optional
    // This is where you put methods that are optional, like settings (optional)
    
    @end
    
    // This overrides the UITableViewDelegate with your own so you can add any methods you would like.
    @protocol MyTableViewDelegate <UITableViewDelegate>
    
    @required
    // This is where you put methods that are required for your custom table to work (optional)
    
    @optional
    // This is where you put methods that are optional, like settings (optional)
    
    @end
    
    // Make sure you add UITableViewDelegate and UITableViewDataSource implementations.
    @interface MyTableView : UITableView <UITableViewDelegate, UITableViewDataSource> {
    
        // Your customer datasource and delegate.
        id <MyTableViewDataSource> myDataSource;
        id <MyTableViewDelegate> myDelegate;
    }
    
    @end
    

    MyTableView.m

    // MyTableView.m
    
    #import "MyTableView.h"
    
    @implementation MyTableView
    
    - (id)initWithFrame:(CGRect)frame
    {
        self = [super initWithFrame:frame];
        if (self) {
            // Initialization code
    
            // This is how you can use your custom method.
            int i = [myDataSource myRequiredMethod];
        }
        return self;
    }
    
    - (void)awakeFromNib {
        // This assigns the delegate and datasource you assigned to File's Owner in your xib to your custom methods
        myDataSource = (id<MyTableViewDataSource>)self.dataSource;
        myDelegate = (id<MyTableViewDelegate>)self.delegate;
        self.delegate = self;
        self.dataSource = self;
    }
    
    // This is an example of how to override an existing UITableView method.
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    
        // This calls the method implemented in your ViewController. See Below.
        NSInteger rows = [myDataSource tableView:tableView numberOfRowsInSection:section];
    
        return rows;
    }
    
    @end
    

    MyViewController.h

    // MyViewController.h
    
    #import "MyTableView.h"
    
    // Use MyTableViewDataSource and MyTableViewDelegate instead of UITableViewDataSource and UITableViewDelegate
    @interface MyViewController : UIViewController <MyTableViewDataSource, MyTableViewDelegate> {
    
    @end
    

    MyViewController.m

    // MyViewController.m
    
    #import "MyViewController.h"
    
    @interface MyViewController ()
    
    @end
    
    @implementation MyViewController
    
    - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
    {
        self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
        if (self) {
            // Custom initialization
        }
        return self;
    }
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    }
    
    // This method will be overridden by myTableViewDataSource
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
        return 1;
    }
    
    - (int)myRequiredMethod {
        return 2;
    }
    

    子类化是制作可重用的自定义 UI 元素的好方法。

    【讨论】:

    • 在调用 API 请求并在 MyTableView.m 中加载数组后调用 [self reloadData] 时,不会显示数据。这个怎么解决?
    【解决方案3】:

    我认为,您仍然应该使用 Controller 类。我希望子类化 UITableView 是一件乏味的工作——如果可能的话,数量要合理。

    让 UIViewController/NoViewController 实现委托和数据源并为特定的 tableView 分配另一个控制器是没有问题的。请注意,数据源和委托不需要是 UITableViewController 的子类。

    看看这个答案:Implement Delegate at Run Time?

    我的 UITableView 没有委托给它的视图控制器,所以这不是问题。

    您必须使用委托和数据源,这就是 TableView 的填充和配置方式。否则你将不得不覆盖 UITableView 的每一个方法——包括私有的,如果你想进入 AppStore 是不行的。在没有子类化的情况下重新创建 UITableView 会更容易。

    【讨论】:

    • 也许我不明白 UITableViewController 的用途。当它的主要任务是拥有 1 个表视图时,我想它是用来代替 UIViewController 的。但是我在不同的 UIViewController 中有一堆复杂的视图,我只想分享一种 UITableView,即我的 ShareUITableView。这不是在卡片上吗?
    • 一个 UITableviewController 只是一个 UIViewController,其中视图属性必须持有一个 UITableView。所有事实都是通过委托和数据源完成的。
    • 在这里查看我的答案:stackoverflow.com/questions/9005254/…
    • 它会解决您的问题,如果您了解,tableviews 是如何生成的,以及如何考虑委托和数据源。你正在给自己制造一个巨大的问题。当你明白这一点时,请回来接受这个答案。
    • 我认为您的链接引用的答案是有道理的,但我不确定这与子类化 UITableViewController 有什么关系。非常确信我不想要 UITableViewController 只是您在链接中概述的方法,对吗?
    猜你喜欢
    • 1970-01-01
    • 2011-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多