如何子类化 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