如何子类化 UITableView?

Posted

技术标签:

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

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

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

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

我将 UITableView 子类化为:

@interface ShareUITableView : UITableView

但没有一个方法被调用。

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

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

有什么想法吗?

【问题讨论】:

【参考方案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。所有事实都是通过委托和数据源完成的。 在这里查看我的答案:***.com/questions/9005254/… 它会解决您的问题,如果您了解,tableviews 是如何生成的,以及如何考虑委托和数据源。你正在给自己制造一个巨大的问题。当你明白这一点时,请回来接受这个答案。 我认为您的链接引用的答案是有道理的,但我不确定这与子类化 UITableViewController 有什么关系。非常确信我不想要 UITableViewController 只是您在链接中概述的方法,对吗?

以上是关于如何子类化 UITableView?的主要内容,如果未能解决你的问题,请参考以下文章

子类化 uitableview 单元而不使用 uitableviewcontroller

子类化 UIViewController 实现 UITableView 委托和数据源:代码重用

如何在许多子类中使用 UITableViewDelegate 子类化 UIViewController

如何在 UITableVIew 下添加 UIButton?

UITableViewCell 中的旋转 UITableView 未显示 initWithFrame: 的位置

子类 uitableview 已经在 UIView 中