Swift3.0之cell的三种创建方式

该文介绍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
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值