在TableView中添加自定义Cell有三种方式:
- 纯代码实现Cell,不依赖xib或storyboard文件
- Storyboard + 代码的方式
- xib文件 + 代码的方式
##方式1: 纯代码实现Cell
###Step 1创建MyCell类
//MyCell.h
#import <UIKit/UIKit.h>
@interface MyCell : UITableViewCell
- (void)setTheValue:(NSString *)str;
@end
#import "MyCell.h"
@interface MyCell ()
@property (nonatomic, strong)UILabel *label;
@end
//MyCell.m
@implementation MyCell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
//创建内容组件
_label = [[UILabel alloc] initWithFrame:CGRectMake(100, 0, 50, 50)];
[self.contentView addSubview:_label];
}
return self;
}
- (void)setTheValue:(NSString *)str {
NSString *text = _label.text;
if(![str isEqualToString:text]) {
_label.text = str;
}
}
@end
Cell内部的内容组件都在initWithStyle: reuseIdentifier:方法中创建。
###Step 2添加TableView 在storyboard中添加一个TableView,并把其中的Cell删除。
###Step 3实现ViewController
//MyViewController.h
#import <UIKit/UIKit.h>
@interface MyViewController : UITableViewController
@end
//MyViewController.m
#import "MyViewController.h"
#import "MyCell.h"
@interface MyViewController ()
@property (nonatomic, copy) NSArray *dataSource;
@end
@implementation MyViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.dataSource = @[@"1", @"2", @"3"];
//必须在这里注册才能确保重用cell
[self.tableView registerClass:[MyCell class] forCellReuseIdentifier:@"CellIdentifier"];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.dataSource.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
MyCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CellIdentifier"];
[cell setTheValue:[self.dataSource objectAtIndex:indexPath.row]];
return cell;
}
@end
由于storyboard中并没有cell,因此必须在代码中注册自定义的cell,以实现cell重用。
方式2: storyboard + 代码
Step 1创建MyCell类
//MyCell.h
#import <UIKit/UIKit.h>
@interface MyCell : UITableViewCell
- (void)setTheValue:(NSString *)str;
@end
//MyCell.m
#import "MyCell.h"
@interface MyCell ()
@property (weak, nonatomic) IBOutlet UILabel *label;
@end
@implementation MyCell
- (void)setTheValue:(NSString *)str {
if(![_label.text isEqualToString:str]) {
_label.text = str;
}
}
@end
Cell的组件内容均在storyboard中实现,因此无需覆盖UITableViewCell的initWithStyle: reuseIdentifier:方法。
Step 2创建TableView和Cell
在storyboard中创建一个TableView,并设置Cell的Identifier和Cell的关联类(MyCell)。然后把一个UILabel拖入Cell中,作为Cell内容组件。最后把storyboard中的label与MyCell中的label通过ctrl-drag的方式连接起来。
Step 3实现ViewController
//MyViewController.h
#import <UIKit/UIKit.h>
@interface MyViewController : UITableViewController
@end
//MyViewController.m
#import "MyViewController.h"
#import "MyCell.h"
@interface MyViewController ()
@property (nonatomic, copy) NSArray *dataSource;
@end
//MyViewController.m
static NSString *CellIdentifier = @"CellIdentifier";
@implementation MyViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.dataSource = @[@"1", @"2", @"3"];
//不要在这里注册cell!去storyboard中注册!
//[self.tableView registerClass:[MyCell class] forCellReuseIdentifier:CellIdentifier];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.dataSource.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
MyCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
NSString *str = [self.dataSource objectAtIndex:indexPath.row];
[cell setTheValue:str];
return cell;
}
@end
你只需在storyboard为自定义cell注册一次即可!!
注意,由于我们已经在storyboard中设置了cell的Identifier,因此切勿在代码中再对cell进行注册,因为这会导致Cell无法正常显示!!!
同时,你可能已经注意到,在storyboard中创建cell后,如果没有设置cell的identifier,编译器会给出警告。也就是说,在storyboard中创建cell时,编译器更希望你在storyboard设置cell的identifier,而不是在代码中注册。
方式3 xib + 代码
Step 1创建MyCell类
//MyCell.h
#import <UIKit/UIKit.h>
@interface MyCell : UITableViewCell
- (void)setTheValue:(NSString *)str;
@end
//MyCell.m
#import "MyCell.h"
@interface MyCell ()
@property (weak, nonatomic) IBOutlet UILabel *label;
@end
@implementation MyCell
- (void)setTheValue:(NSString *)str {
if(![_label.text isEqualToString:str]) {
_label.text = str;
}
}
@end
Cell的组件内容均在xib文件中实现,因此无需覆盖UITableViewCell的initWithStyle: reuseIdentifier:方法。
###Step 2创建TableView和Cell 在storyboard中创建一个TabelView,并删除其中的cell。
在项目创建一个名为CellXib的xib文件,用于表示cell。打开xib文件,往其中拖入一个label。
###Step 3创建ViewController
//MyViewController.h
#import <UIKit/UIKit.h>
@interface MyViewController : UITableViewController
@end
//MyViewController.m
#import "MyViewController.h"
#import "MyCell.h"
@interface MyViewController ()
@property (nonatomic, copy) NSArray *dataSource;
@end
static NSString *CellIdentifier = @"CellIdentifier";
@implementation MyViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.dataSource = @[@"1", @"2", @"3"];
//仅需要在代码中注册一次
UINib *nib = [UINib nibWithNibName:@"CellXib" bundle:nil];
[self.tableView registerNib:nib forCellReuseIdentifier:CellIdentifier];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.dataSource.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
MyCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
NSString *str = [self.dataSource objectAtIndex:indexPath.row];
[cell setTheValue:str];
return cell;
}
@end
与方式2不同的是,使用xib后,你只需用代码注册cell即可。
##总结 纯代码实现Cell
- 优点: 我们可以复用这个cell。
- 缺点: 在编写代码时,无法直观的看到cell的样子。
- 只需要在代码中注册cell。
- 不推荐使用
storyboard + 代码
- 优点: 可以直观的看到cell嵌入到TabelView的效果,同时也方便对cell进行管理。
- 缺点: 无法复用这个cell。因为cell和storyboard紧密关联。(storyboard的一大特点就是不能拥有独立, 可复用的view)
- 只需要在storyboard中注册cell。
- 当我们不需要复用cell时,可以选择此方法
xib文件 + 代码
- 优点: 可以直观的看到cell的样子。
- 需要同时管理storyboard和xib文件,有点麻烦。
- 只需要在代码中注册cell。
- 当我们需要复用cell时,可以选择此方法。