该文介绍Swift3.0中分别采用系统、xib、代码自定义三种方式创建UITableViewCell,并与Objective-C创建cell作对比,比较语法的不同之处

  下图是Objective-C编写的创建cell的项目结构:

Swift3.0之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代码的项目结构:

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

  需要注意的是在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 TableViewControllerUITableViewController {
 
    //MARK: - View life cycle
    override func viewDidLoad() {
        super.viewDidLoad()
 
        //使tableView向下20个点
        tableView.contentInset UIEdgeInsetsMake(20000)
        print(NSStringFromClass(XibTableViewCell.self), XibTableViewCell.reuseIdentifier)
        //Swift有命名空间的概念,使得NSStringFromClass这个方法返回的不只是类名,签名还有类名所在文件相对路径
        tableView.register(UINib.init(nibName"XibTableViewCell"bundlenil), forCellReuseIdentifierXibTableViewCell.reuseIdentifier)
        tableView.register(CustomTableViewCell.selfforCellReuseIdentifierCustomTableViewCell.reuseIdentifier)
    }
 
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
 
    //MARK: - Construction method
    //必须重写此方法,UITableViewController才能成功调用空的构造方法
    override init(styleUITableViewStyle) {
        super.init(stylestyle)
        print(#function)
    }
     
    //必须重写此方法,否则编译无法通过
    required init?(coder aDecoderNSCoder) {
        super.init(coderaDecoder)
        print(#function)
    }
 
    //重写此方法使得UITableViewController能够调用空的构造方法
    override init(nibName nibNameOrNilString?, bundle nibBundleOrNilBundle?) {
        super.init(nibNamenibNameOrNilbundlenibBundleOrNil)
        print(#function)
    }
     
}
 
extension TableViewController {
    //MARK: - UITableViewDelegate
    override func numberOfSections(in tableViewUITableView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        return 3
    }
     
    override func tableView(_ tableViewUITableViewnumberOfRowsInSection sectionInt) -> Int {
        // #warning Incomplete implementation, return the number of rows
        return 1
    }
     
    override func tableView(_ tableViewUITableViewcellForRowAt indexPathIndexPath) -> UITableViewCell {
        switch indexPath.section {
        case 0:
            let systemCell SystemTableViewCell.cell(tableViewtableViewindexPathindexPath)
            return systemCell
        case 1:
            let xibCell XibTableViewCell.cell(tableViewtableViewindexPathindexPath)
            return xibCell
        default:
            let customCell CustomTableViewCell.cell(tableViewtableViewindexPathindexPath)
            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 SystemTableViewCellUITableViewCell {
 
    static let reuseIdentifier "SystemCell"
     
    static func cell(tableViewUITableViewindexPathIndexPath) -> SystemTableViewCell{
        print(#function)
        var cellSystemTableViewCell?
        cell tableView.dequeueReusableCell(withIdentifierSystemTableViewCell.reuseIdentifierasSystemTableViewCell?
        if cell == nil {
            cell SystemTableViewCell(styleUITableViewCellStyle.defaultreuseIdentifierSystemTableViewCell.reuseIdentifier)
        }
        cell?.imageView?.image UIImage(named"image")
        cell?.textLabel?.text "System"
        return cell!
    }
     
    override init(styleUITableViewCellStylereuseIdentifierString?) {
        super.init(stylestylereuseIdentifierreuseIdentifier)
        print(#function)
    }
     
    required init?(coder aDecoderNSCoder) {
        super.init(coderaDecoder)
        print(#function)
    }
     
    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
        print(#function)
    }
 
    override func setSelected(_ selectedBoolanimatedBool) {
        super.setSelected(selectedanimatedanimated)
 
        // 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 XibTableViewCellUITableViewCell {
 
    static let reuseIdentifier "XibCell"
     
    @IBOutlet weak var xibImageViewUIImageView!
     
    @IBOutlet weak var xibTextLabelUILabel!
     
    static func cell(tableViewUITableViewindexPathIndexPath) -> XibTableViewCell {
        print(#function)
        var cellXibTableViewCell?
        cell tableView.dequeueReusableCell(withIdentifierXibTableViewCell.reuseIdentifierasXibTableViewCell?
        cell?.xibImageView.image UIImage(named"image")
        cell?.xibTextLabel.text "Xib"
        return cell!
    }
     
    override init(styleUITableViewCellStylereuseIdentifierString?) {
        super.init(stylestylereuseIdentifierreuseIdentifier)
        print(#function)
    }
     
    required init?(coder aDecoderNSCoder) {
        super.init(coderaDecoder)
        print(#function)
    }
     
    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
        print(#function)
    }
 
    override func setSelected(_ selectedBoolanimatedBool) {
        super.setSelected(selectedanimatedanimated)
 
        // 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 CustomTableViewCellUITableViewCell {
 
    static let reuseIdentifier "CustomCell"
     
    ///左侧imageView
    var customImageViewUIImageView!
    ///右侧text label
    var customTextLabelUILabel!
     
    static func cell(tableViewUITableViewindexPathIndexPath) -> CustomTableViewCell {
        print(#function)
        var cellCustomTableViewCell?
        cell = (tableView.dequeueReusableCell(withIdentifierCustomTableViewCell.reuseIdentifierasCustomTableViewCell)
        cell?.customImageView.image UIImage(named"image")
        cell?.customTextLabel.text "Custom"
        return cell!
    }
     
    override init(styleUITableViewCellStylereuseIdentifierString?) {
        super.init(stylestylereuseIdentifierreuseIdentifier)
        print(#function)
        self.setupContentView()
    }
     
    required init?(coder aDecoderNSCoder) {
        super.init(coderaDecoder)
        print(#function)
    }
     
    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
        print(#function)
    }
 
    override func setSelected(_ selectedBoolanimatedBool) {
        super.setSelected(selectedanimatedanimated)
 
        // Configure the view for the selected state
    }
     
    ///添加内容视图
    private func setupContentView() {
        customImageView UIImageView()
        self.contentView.addSubview(customImageView)
         
        customTextLabel UILabel()
        self.contentView.addSubview(customTextLabel)
         
        let imageViewHCGFloat self.contentView.frame.size.height
        customImageView.frame CGRect(x16y0widthimageViewHheightimageViewH)
        customTextLabel.frame CGRect(xcustomImageView.frame.maxX+16ycustomImageView.frame.minYwidth200heightcustomImageView.frame.height)
    }
 
}

   此处内容视图的子视图未添加约束,只是简单地设置了frame,当然,在真实项目中可在此处用cocoapods导入snapkit框架作适配,即Objective-C语言masonry矿建的Swift版本。

转载自:https://www.cnblogs.com/keqipu/p/6580215.html

相关文章:

  • 2021-11-19
  • 2021-10-31
  • 2021-11-25
  • 2021-12-25
  • 2021-06-07
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-03-02
  • 2021-12-04
相关资源
相似解决方案