该文介绍Swift3.0中分别采用系统、xib、代码自定义三种方式创建UITableViewCell,并与Objective-C创建cell作对比,比较语法的不同之处
下图是Objective-C编写的创建cell的项目结构:
可以看到在APPDelegate中,我创建了一个继承UITableViewController的控制器,并作为根视图控制器显示
以下是ViewController实现文件中的代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
//
// TableViewController.m
// 20170317-cell系统方法调用顺序
//
// Created by 柯其谱 on 17/3/18.
// Copyright © 2017年 柯其谱. All rights reserved.
//
#import "TableViewController.h"
#import "SystemTableViewCell.h"
#import "XibTableViewCell.h"
#import "CustomTableViewCell.h"
@interface
TableViewController ()
@end
@implementation
TableViewController
- (
void
)viewDidLoad {
[
super
viewDidLoad];
// //系统创建的cell不用注册
// [self.tableView registerClass:[SystemTableViewCell class] forCellReuseIdentifier:SystemTableViewCellID];
//xib和自定义cell创建的cell必须注册
[
self
.tableView registerNib:[UINib nibWithNibName:
NSStringFromClass
([XibTableViewCell
class
]) bundle:
nil
] forCellReuseIdentifier:XibTableViewCellID];
[
self
.tableView registerClass:[CustomTableViewCell
class
] forCellReuseIdentifier:CustomTableViewCellID];
}
- (
void
)didReceiveMemoryWarning {
[
super
didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (
NSInteger
)numberOfSectionsInTableView:(UITableView *)tableView {
return
3;
}
- (
NSInteger
)tableView:(UITableView *)tableView numberOfRowsInSection:(
NSInteger
)section {
return
1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(
NSIndexPath
*)indexPath {
if
(indexPath.section == 0) {
SystemTableViewCell *systemCell = [SystemTableViewCell cellWithTableView:tableView indexPath:indexPath];
return
systemCell;
}
else
if
(indexPath.section == 1) {
XibTableViewCell *xibCell = [XibTableViewCell cellWithTableView:tableView indexPath:indexPath];
return
xibCell;
}
else
{
CustomTableViewCell *customCell = [CustomTableViewCell cellWithTableView:tableView indexPath:indexPath];
return
customCell;
}
}
@end
|
由于代码较为简单,我这里就不作解释,需要注意的是为了控制器的瘦身,我将cell的创建和内容显示全部放在了各自的cell实现文件中,且本文三种cell创建方式显示的cell为同一样式,这里是为了简单起见,到了复杂一点的项目就可将所有的有关cell代码全部写在cell文件中
以下是SystemTableViewCell,即cell的系统样式的实现代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
//
// SystemTableViewCell.m
// 20170317-cell系统方法调用顺序
//
// Created by 柯其谱 on 17/3/17.
// Copyright © 2017年 柯其谱. All rights reserved.
//
#import "SystemTableViewCell.h"
NSString
*
const
SystemTableViewCellID = @
"SystemCell"
;
@implementation
SystemTableViewCell
+ (instancetype)cellWithTableView:(UITableView *)tableView indexPath:(
NSIndexPath
*)indexPath {
NSLog
(@
"%s"
, __func__);
SystemTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SystemTableViewCellID];
if
(cell ==
nil
) {
cell = [[SystemTableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:SystemTableViewCellID];
}
cell.imageView.image = [UIImage imageNamed:@
"image"
];
cell.textLabel.text = @
"System"
;
return
cell;
}
//系统创建的cell调用,其他不调用
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(
NSString
*)reuseIdentifier {
if
(
self
= [
super
initWithStyle:style reuseIdentifier:reuseIdentifier]) {
NSLog
(@
"%s"
, __func__);
}
return
self
;
}
- (instancetype)initWithCoder:(
NSCoder
*)aDecoder {
if
(
self
= [
super
initWithCoder:aDecoder]) {
NSLog
(@
"%s"
, __func__);
}
return
self
;
}
- (
void
)awakeFromNib {
[
super
awakeFromNib];
// Initialization code
NSLog
(@
"%s"
, __func__);
}
- (
void
)setSelected:(
BOOL
)selected animated:(
BOOL
)animated {
[
super
setSelected:selected animated:animated];
// Configure the view for the selected state
}
@end
|
本文也顺便研究了各种创建cell的方式的系统方法调用顺序,可以看到,控制台只打印了initWithStyle方法,也就是说,系统样式创建的cell只在cell未开始复用时调用该方法,其他方法不调用。
以下是XibTableViewCell,即xib创建cell的方式,本文创建的cell内容视图都与系统的default样式相似,故xib的约束未贴出:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
//
// XibTableViewCell.m
// 20170317-cell系统方法调用顺序
//
// Created by 柯其谱 on 17/3/17.
// Copyright © 2017年 柯其谱. All rights reserved.
//
#import "XibTableViewCell.h"
NSString
*
const
XibTableViewCellID = @
"XibCell"
;
@implementation
XibTableViewCell
+ (instancetype)cellWithTableView:(UITableView *)tableView indexPath:(
NSIndexPath
*)indexPath {
NSLog
(@
"%s"
, __func__);
XibTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:XibTableViewCellID];
cell.xibImageView.image = [UIImage imageNamed:@
"image"
];
cell.xibTextLabel.text = @
"Xib"
;
return
cell;
}
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(
NSString
*)reuseIdentifier {
if
(
self
= [
super
initWithStyle:style reuseIdentifier:reuseIdentifier]) {
NSLog
(@
"%s"
, __func__);
}
return
self
;
}
//xib创建cell先调用此方法,再调用awakeFromNib
- (instancetype)initWithCoder:(
NSCoder
*)aDecoder {
if
(
self
= [
super
initWithCoder:aDecoder]) {
NSLog
(@
"%s"
, __func__);
}
return
self
;
}
- (
void
)awakeFromNib {
[
super
awakeFromNib];
// Initialization code
NSLog
(@
"%s"
, __func__);
}
- (
void
)setSelected:(
BOOL
)selected animated:(
BOOL
)animated {
[
super
setSelected:selected animated:animated];
// Configure the view for the selected state
}
@end
|
控制台中,先打印initWithCoder方法名,再打印awakeFromNib方法名,也就是说用xib创建的cell会先后调用这两个方法,可以在awakeFromNib中作一些cell的初始化工作
以下是CustomCell实现文件,即代码自定义创建cell的方式,由于内容视图较为简单,这里未做约束:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
//
// CustomTableViewCell.m
// 20170317-cell系统方法调用顺序
//
// Created by 柯其谱 on 17/3/17.
// Copyright © 2017年 柯其谱. All rights reserved.
//
#import "CustomTableViewCell.h"
NSString
*
const
CustomTableViewCellID = @
"CustomCell"
;
@implementation
CustomTableViewCell
+ (instancetype)cellWithTableView:(UITableView *)tableView indexPath:(
NSIndexPath
*)indexPath {
NSLog
(@
"%s"
, __func__);
CustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CustomTableViewCellID];
cell.customImageView.image = [UIImage imageNamed:@
"image"
];
cell.customTextLabel.text = @
"Custom"
;
return
cell;
}
//代码自定义cell调用,其他不调用
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(
NSString
*)reuseIdentifier {
if
(
self
= [
super
initWithStyle:style reuseIdentifier:reuseIdentifier]) {
NSLog
(@
"%s"
, __func__);
[
self
setupContentView];
}
return
self
;
}
- (instancetype)initWithCoder:(
NSCoder
*)aDecoder {
if
(
self
= [
super
initWithCoder:aDecoder]) {
NSLog
(@
"%s"
, __func__);
[
self
setupContentView];
}
return
self
;
}
- (
void
)awakeFromNib {
[
super
awakeFromNib];
// Initialization code
NSLog
(@
"%s"
, __func__);
}
- (
void
)setupContentView {
UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMake(16, 0,
self
.contentView.frame.size.height,
self
.contentView.frame.size.height)];
self
.customImageView = imageView;
[
self
.contentView addSubview:imageView];
UILabel *textLabel = [[UILabel alloc]initWithFrame:CGRectMake(CGRectGetMaxX(imageView.frame)+16, 0, 100, CGRectGetHeight(imageView.frame))];
self
.customTextLabel = textLabel;
[
self
.contentView addSubview:textLabel];
}
- (
void
)setSelected:(
BOOL
)selected animated:(
BOOL
)animated {
[
super
setSelected:selected animated:animated];
// Configure the view for the selected state
}
@end
|
代码自定义创建cell的方式与系统样式相似,会调用initWithStyle,重写此方法并添加内容视图,以及添加内容视图子视图的约束。
以上是Objective-C语言编写的简单创建cell的代码,接下来介绍Swift3.0编写的创建cell的代码,代码实现的目标与Objective-C完全一致,只是部分代码发生了改变
下图是Swift3.0代码的项目结构:
需要注意的是在APPDelegate文件中,初始化UITableViewController子类的方法与Objective-C略有不同,UITableViewController子类中必须重写init(style: UITableViewStyle)方法才能顺利调用UITableViewController子类的空构造方法,否则编译器无法通过
以下是UITableViewController子类中的代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
//
// TableViewController.Swift
// Swift demo - 三种cell创建方式
//
// Created by 柯其谱 on 17/3/18.
// Copyright © 2017年 柯其谱. All rights reserved.
//
import
UIKit
class
TableViewController
:
UITableViewController
{
//MARK: - View life cycle
override
func
viewDidLoad
() {
super
.
viewDidLoad
()
//使tableView向下20个点
tableView
.
contentInset
=
UIEdgeInsetsMake
(
20
,
0
,
0
,
0
)
print
(
NSStringFromClass
(
XibTableViewCell
.
self
),
XibTableViewCell
.
reuseIdentifier
)
//Swift有命名空间的概念,使得NSStringFromClass这个方法返回的不只是类名,签名还有类名所在文件相对路径
tableView
.
register
(
UINib
.
init
(
nibName
:
"XibTableViewCell"
,
bundle
:
nil
),
forCellReuseIdentifier
:
XibTableViewCell
.
reuseIdentifier
)
tableView
.
register
(
CustomTableViewCell
.
self
,
forCellReuseIdentifier
:
CustomTableViewCell
.
reuseIdentifier
)
}
override
func
didReceiveMemoryWarning
() {
super
.
didReceiveMemoryWarning
()
// Dispose of any resources that can be recreated.
}
//MARK: - Construction method
//必须重写此方法,UITableViewController才能成功调用空的构造方法
override
init
(
style
:
UITableViewStyle
) {
super
.
init
(
style
:
style
)
print
(#
function
)
}
//必须重写此方法,否则编译无法通过
required
init
?(
coder
aDecoder
:
NSCoder
) {
super
.
init
(
coder
:
aDecoder
)
print
(#
function
)
}
//重写此方法使得UITableViewController能够调用空的构造方法
override
init
(
nibName
nibNameOrNil
:
String
?,
bundle
nibBundleOrNil
:
Bundle
?) {
super
.
init
(
nibName
:
nibNameOrNil
,
bundle
:
nibBundleOrNil
)
print
(#
function
)
}
}
extension
TableViewController
{
//MARK: - UITableViewDelegate
override
func
numberOfSections
(
in
tableView
:
UITableView
) -
>
Int
{
// #warning Incomplete implementation, return the number of sections
return
3
}
override
func
tableView
(
_
tableView
:
UITableView
,
numberOfRowsInSection
section
:
Int
) -
>
Int
{
// #warning Incomplete implementation, return the number of rows
return
1
}
override
func
tableView
(
_
tableView
:
UITableView
,
cellForRowAt
indexPath
:
IndexPath
) -
>
UITableViewCell
{
switch
indexPath
.
section
{
case
0
:
let
systemCell
=
SystemTableViewCell
.
cell
(
tableView
:
tableView
,
indexPath
:
indexPath
)
return
systemCell
case
1
:
let
xibCell
=
XibTableViewCell
.
cell
(
tableView
:
tableView
,
indexPath
:
indexPath
)
return
xibCell
default
:
let
customCell
=
CustomTableViewCell
.
cell
(
tableView
:
tableView
,
indexPath
:
indexPath
)
return
customCell
}
}
}
|
与Objective-C不同的是,Swift3.0需要重写一些构造方法,另外一点,在cell的nib注册方法中,Swift直接将cell的nib文件名作为参数传入,这是因为Swift的命名空间机制,使得每一个类都有一个唯一的命名空间,类名便多了一些诸如项目名的前缀,若此处坚持使用跟Objective-C注册cell 的方式一致,使用NSStringFromClass([XibTableViewCell class]方法作为参数传入,则运行会导致奔溃,cell始终是空值。其余代码与Objective-C大体一致。
以下是SystemTableViewCell文件中的代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
//
// SystemTableViewCell.Swift
// Swift demo - 三种cell创建方式
//
// Created by 柯其谱 on 17/3/18.
// Copyright © 2017年 柯其谱. All rights reserved.
//
import
UIKit
class
SystemTableViewCell
:
UITableViewCell
{
static
let
reuseIdentifier
=
"SystemCell"
static
func
cell
(
tableView
:
UITableView
,
indexPath
:
IndexPath
) -
>
SystemTableViewCell
{
print
(#
function
)
var
cell
:
SystemTableViewCell
?
cell
=
tableView
.
dequeueReusableCell
(
withIdentifier
:
SystemTableViewCell
.
reuseIdentifier
)
as
!
SystemTableViewCell
?
if
cell
==
nil
{
cell
=
SystemTableViewCell
(
style
:
UITableViewCellStyle
.
default
,
reuseIdentifier
:
SystemTableViewCell
.
reuseIdentifier
)
}
cell
?.
imageView
?.
image
=
UIImage
(
named
:
"image"
)
cell
?.
textLabel
?.
text
=
"System"
return
cell
!
}
override
init
(
style
:
UITableViewCellStyle
,
reuseIdentifier
:
String
?) {
super
.
init
(
style
:
style
,
reuseIdentifier
:
reuseIdentifier
)
print
(#
function
)
}
required
init
?(
coder
aDecoder
:
NSCoder
) {
super
.
init
(
coder
:
aDecoder
)
print
(#
function
)
}
override
func
awakeFromNib
() {
super
.
awakeFromNib
()
// Initialization code
print
(#
function
)
}
override
func
setSelected
(
_
selected
:
Bool
,
animated
:
Bool
) {
super
.
setSelected
(
selected
,
animated
:
animated
)
// Configure the view for the selected state
}
}
|
此处与Objective-C代码类似,这里不作赘述,调用方式也一致
以下是XibTableViewCell文件代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
//
// XibTableViewCell.Swift
// Swift demo - 三种cell创建方式
//
// Created by 柯其谱 on 17/3/18.
// Copyright © 2017年 柯其谱. All rights reserved.
//
import
UIKit
class
XibTableViewCell
:
UITableViewCell
{
static
let
reuseIdentifier
=
"XibCell"
@IBOutlet
weak
var
xibImageView
:
UIImageView
!
@IBOutlet
weak
var
xibTextLabel
:
UILabel
!
static
func
cell
(
tableView
:
UITableView
,
indexPath
:
IndexPath
) -
>
XibTableViewCell
{
print
(#
function
)
var
cell
:
XibTableViewCell
?
cell
=
tableView
.
dequeueReusableCell
(
withIdentifier
:
XibTableViewCell
.
reuseIdentifier
)
as
!
XibTableViewCell
?
cell
?.
xibImageView
.
image
=
UIImage
(
named
:
"image"
)
cell
?.
xibTextLabel
.
text
=
"Xib"
return
cell
!
}
override
init
(
style
:
UITableViewCellStyle
,
reuseIdentifier
:
String
?) {
super
.
init
(
style
:
style
,
reuseIdentifier
:
reuseIdentifier
)
print
(#
function
)
}
required
init
?(
coder
aDecoder
:
NSCoder
) {
super
.
init
(
coder
:
aDecoder
)
print
(#
function
)
}
override
func
awakeFromNib
() {
super
.
awakeFromNib
()
// Initialization code
print
(#
function
)
}
override
func
setSelected
(
_
selected
:
Bool
,
animated
:
Bool
) {
super
.
setSelected
(
selected
,
animated
:
animated
)
// Configure the view for the selected state
}
}
|
最后是CustomTableViewCell文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
//
// CustomTableViewCell.Swift
// Swift demo - 三种cell创建方式
//
// Created by 柯其谱 on 17/3/18.
// Copyright © 2017年 柯其谱. All rights reserved.
//
import
UIKit
class
CustomTableViewCell
:
UITableViewCell
{
static
let
reuseIdentifier
=
"CustomCell"
///左侧imageView
var
customImageView
:
UIImageView
!
///右侧text label
var
customTextLabel
:
UILabel
!
static
func
cell
(
tableView
:
UITableView
,
indexPath
:
IndexPath
) -
>
CustomTableViewCell
{
print
(#
function
)
var
cell
:
CustomTableViewCell
?
cell
= (
tableView
.
dequeueReusableCell
(
withIdentifier
:
CustomTableViewCell
.
reuseIdentifier
)
as
!
CustomTableViewCell
)
cell
?.
customImageView
.
image
=
UIImage
(
named
:
"image"
)
cell
?.
customTextLabel
.
text
=
"Custom"
return
cell
!
}
override
init
(
style
:
UITableViewCellStyle
,
reuseIdentifier
:
String
?) {
super
.
init
(
style
:
style
,
reuseIdentifier
:
reuseIdentifier
)
print
(#
function
)
self
.
setupContentView
()
}
required
init
?(
coder
aDecoder
:
NSCoder
) {
super
.
init
(
coder
:
aDecoder
)
print
(#
function
)
}
override
func
awakeFromNib
() {
super
.
awakeFromNib
()
// Initialization code
print
(#
function
)
}
override
func
setSelected
(
_
selected
:
Bool
,
animated
:
Bool
) {
super
.
setSelected
(
selected
,
animated
:
animated
)
// Configure the view for the selected state
}
///添加内容视图
private
func
setupContentView
() {
customImageView
=
UIImageView
()
self
.
contentView
.
addSubview
(
customImageView
)
customTextLabel
=
UILabel
()
self
.
contentView
.
addSubview
(
customTextLabel
)
let
imageViewH
:
CGFloat
=
self
.
contentView
.
frame
.
size
.
height
customImageView
.
frame
=
CGRect
(
x
:
16
,
y
:
0
,
width
:
imageViewH
,
height
:
imageViewH
)
customTextLabel
.
frame
=
CGRect
(
x
:
customImageView
.
frame
.
maxX
+
16
,
y
:
customImageView
.
frame
.
minY
,
width
:
200
,
height
:
customImageView
.
frame
.
height
)
}
}
|
此处内容视图的子视图未添加约束,只是简单地设置了frame,当然,在真实项目中可在此处用cocoapods导入snapkit框架作适配,即Objective-C语言masonry矿建的Swift版本。
转载自:https://www.cnblogs.com/keqipu/p/6580215.html