如何从Xib文件加载自定义uitableviewcell ?

问题很简单:如何从Xib文件加载自定义UITableViewCell ?这样做允许您使用Interface Builder来设计单元格。由于内存管理问题,答案显然并不简单。这个线程提到了这个问题,并提出了一个解决方案,但是nda发布之前,缺乏代码。下面是一个长线程,它讨论了这个问题,但没有提供一个确定的答案。

下面是我使用的一些代码:

static NSString *CellIdentifier = @"MyCellIdentifier";


MyCell *cell = (MyCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:CellIdentifier owner:self options:nil];
cell = (MyCell *)[nib objectAtIndex:0];
}

要使用这段代码,创建MyCell.m/.h, UITableViewCell的一个新子类,并为你想要的组件添加IBOutlets。然后创建一个新的“Empty XIB”文件。在IB中打开Xib文件,添加一个UITableViewCell对象,将其标识符设置为“MyCellIdentifier”,并将其类设置为MyCell并添加组件。最后,将IBOutlets连接到组件。注意,我们没有在IB中设置文件的所有者。

其他方法主张设置文件的所有者,如果Xib没有通过额外的工厂类加载,则警告内存泄漏。我在Instruments/Leaks下测试了上面的内容,没有发现内存泄漏。

那么从xib加载单元格的规范方法是什么呢?我们设置文件的所有者吗?我们需要工厂吗?如果是,工厂的代码是什么样子的?如果有多种解决方案,让我们来阐明每一种方案的优缺点。

219880 次浏览

我不知道是否有一个规范的方法,但以下是我的方法:

  • 为ViewController创建一个xib
  • 将File Owner类设置为UIViewController
  • 删除视图并添加一个UITableViewCell
  • 将UITableViewCell的类设置为自定义类
  • 设置UITableViewCell的标识符
  • 设置你的视图控制器视图的出口到你的UITableViewCell

并使用这段代码:

MyCustomViewCell *cell = (MyCustomViewCell *)[_tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
UIViewController* c = [[UIViewController alloc] initWithNibName:CellIdentifier bundle:nil];
cell = (MyCustomViewCell *)c.view;
[c release];
}

在你的例子中,使用

[nib objectAtIndex:0]

如果苹果改变xib中项目的顺序,可能会中断。

下面是我一直用于从xib中创建自定义单元格的类方法:

+ (CustomCell*) createNewCustomCellFromNib {


NSArray* nibContents = [[NSBundle mainBundle]
loadNibNamed:@"CustomCell" owner:self options:NULL];


NSEnumerator *nibEnumerator = [nibContents objectEnumerator];
CustomCell *customCell= nil;
NSObject* nibItem = nil;


while ( (nibItem = [nibEnumerator nextObject]) != nil) {


if ( [nibItem isKindOfClass: [CustomCell class]]) {
customCell = (CustomCell*) nibItem;


if ([customCell.reuseIdentifier isEqualToString: @"CustomCell"]) {
break; // we have a winner
}
else
fuelEntryCell = nil;
}
}
return customCell;
}

然后,在XIB中设置类名和重用标识符。之后,我可以在视图控制器中调用那个方法而不是

[[UITableViewCell] alloc] initWithFrame:]

它已经足够快了,并且在我的两个运输应用程序中使用。它比调用[nib objectAtIndex:0]更可靠,至少在我看来,比Stephan Burlot的例子更可靠,因为你保证只从正确类型的XIB中获取视图。

从XIB加载UITableViewCells可以节省大量代码,但通常会导致糟糕的滚动速度(实际上,不是XIB,而是过度使用UIViews导致了这一点)。

我建议你看一下这个:参考链接

我为此所做的是在控制器类中声明一个IBOutlet UITableViewCell *cell。 然后调用NSBundle loadNibNamed类方法,该方法将UITableViewCell提供给上面声明的单元格

对于xib,我将创建一个空的xib,并在IB中添加UITableViewCell对象,在那里它可以根据需要设置。这个视图随后被连接到控制器类中的单元IBOutlet

- (UITableViewCell *)tableView:(UITableView *)table
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"%@ loading RTEditableCell.xib", [self description] );


static NSString *MyIdentifier = @"editableCellIdentifier";
cell = [table dequeueReusableCellWithIdentifier:MyIdentifier];


if(cell == nil) {
[[NSBundle mainBundle] loadNibNamed:@"RTEditableCell"
owner:self
options:nil];
}


return cell;
}

NSBundle attachments loadNibNamed (ADC login) . bb0

cocoawithlove.com文章我从(获得电话号码样本应用程序)的概念来源

这里有两个方法,原作者是由IB工程师推荐的

更多细节请参见实际文章。我更喜欢第二种方法,因为它看起来更简单。

方法# 1:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"BDCustomCell"];
if (cell == nil) {
// Create a temporary UIViewController to instantiate the custom cell.
UIViewController *temporaryController = [[UIViewController alloc] initWithNibName:@"BDCustomCell" bundle:nil];
// Grab a pointer to the custom cell.
cell = (BDCustomCell *)temporaryController.view;
[[cell retain] autorelease];
// Release the temporary UIViewController.
[temporaryController release];
}


return cell;
}

方法# 2:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"BDCustomCell"];
if (cell == nil) {
// Load the top-level objects from the custom cell XIB.
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"BDCustomCell" owner:self options:nil];
// Grab a pointer to the first object (presumably the custom cell, as that's all the XIB should contain).
cell = [topLevelObjects objectAtIndex:0];
}


return cell;
}

< >强更新(2014): 方法#2仍然有效,但不再有关于它的文档。它曾经在官方文档中,但现在为了支持故事板而被删除 我在Github上发布了一个工作示例:
https://github.com/bentford/NibTableCellExample < / p >

Swift 4.2编辑

override func viewDidLoad() {
super.viewDidLoad()


// Do any additional setup after loading the view.
self.tblContacts.register(UINib(nibName: CellNames.ContactsCell, bundle: nil), forCellReuseIdentifier: MyIdentifier)
}


func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {


let cell = tableView.dequeueReusableCell(withIdentifier: MyIdentifier, for: indexPath) as! ContactsCell


return cell
}

如果您正在使用Interface Builder来创建单元格,请检查是否在检查器中设置了标识符。然后在调用dequeueReusableCellWithIdentifier时检查是否相同。

我无意中忘记在一个表较多的项目中设置一些标识符,性能变化就像白天和黑夜一样。

把肖恩·克雷弗的答案整理了一下。

BBCell.h:

#import <UIKit/UIKit.h>


@interface BBCell : UITableViewCell {
}


+ (BBCell *)cellFromNibNamed:(NSString *)nibName;


@end

BBCell.m:

#import "BBCell.h"


@implementation BBCell


+ (BBCell *)cellFromNibNamed:(NSString *)nibName {
NSArray *nibContents = [[NSBundle mainBundle] loadNibNamed:nibName owner:self options:NULL];
NSEnumerator *nibEnumerator = [nibContents objectEnumerator];
BBCell *customCell = nil;
NSObject* nibItem = nil;
while ((nibItem = [nibEnumerator nextObject]) != nil) {
if ([nibItem isKindOfClass:[BBCell class]]) {
customCell = (BBCell *)nibItem;
break; // we have a winner
}
}
return customCell;
}


@end

我让UITableViewCell的所有BBCell的子类,然后替换标准

cell = [[[BBDetailCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"BBDetailCell"] autorelease];

:

cell = (BBDetailCell *)[BBDetailCell cellFromNibNamed:@"BBDetailCell"];

下面是我的方法:从XIB文件加载自定义UITableViewCells

其思想是创建一个带有UITableViewCell属性的SampleCell子类,并为您需要从代码中配置的每个自定义子视图创建一个属性。然后创建一个SampleCell。xib文件。在这个nib文件中,将文件所有者更改为SampleCell。添加内容UIView大小以适应您的需要。添加和配置你想要的所有子视图(标签、图像视图、按钮等)。最后,将内容视图和子视图链接到文件所有者。

重新加载NIB是昂贵的。最好只加载一次,然后在需要单元格时实例化对象。注意,你可以添加UIImageViews等到nib,甚至多个单元格,使用这个方法(苹果的“registerNIB”iOS5只允许一个顶级对象- Bug 10580062 "iOS5 tableView registerNib: overloaded restricted "

.

所以我的代码如下-你在NIB读取一次(在初始化,就像我做的或在viewDidload -随便什么。从那时起,您将nib实例化到对象中,然后选择您需要的对象。这比反复加载笔尖要有效得多。

static UINib *cellNib;


+ (void)initialize
{
if(self == [ImageManager class]) {
cellNib = [UINib nibWithNibName:@"ImageManagerCell" bundle:nil];
assert(cellNib);
}
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellID = @"TheCell";


UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
if(cell == nil) {
NSArray *topLevelItems = [cellNib instantiateWithOwner:nil options:nil];
NSUInteger idx = [topLevelItems indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop)
{
UITableViewCell *cell = (UITableViewCell *)obj;
return [cell isKindOfClass:[UITableViewCell class]] && [cell.reuseIdentifier isEqualToString:cellID];
} ];
assert(idx != NSNotFound);
cell = [topLevelItems objectAtIndex:idx];
}
cell.textLabel.text = [NSString stringWithFormat:@"Howdie %d", indexPath.row];


return cell;
}

我使用了bentford的方法# 2:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"BDCustomCell"];
if (cell == nil) {
// Load the top-level objects from the custom cell XIB.
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"BDCustomCell" owner:self options:nil];
// Grab a pointer to the first object (presumably the custom cell, as that's all the XIB should contain).
cell = [topLevelObjects objectAtIndex:0];
}


return cell;
}

它是有效的,但要注意在自定义UITableViewCell .xib文件中连接到File's Owner

通过在你的loadNibNamed语句中传递owner:self,你将UITableViewController设置为你的UITableViewCell的文件所有者。

如果你拖拽到IB中的头文件来设置动作和出口,默认情况下它会将它们设置为file 's Owner。

loadNibNamed:owner:options中,Apple的代码将尝试在你的UITableViewController上设置属性,因为它是所有者。但是你没有在那里定义这些属性,所以你会得到一个关于键值编码兼容的错误:

*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason:     '[<MyUITableViewController 0x6a383b0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key myLabel.'

如果一个事件被触发,你会得到一个NSInvalidArgumentException:

-[MyUITableViewController switchValueDidChange:]: unrecognized selector sent to instance 0x8e9acd0
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[MyUITableViewController switchValueDidChange:]: unrecognized selector sent to instance 0x8e9acd0'
*** First throw call stack:
(0x1903052 0x15eed0a 0x1904ced 0x1869f00 0x1869ce2 0x1904ec9 0x5885c2 0x58855a 0x62db76 0x62e03f 0x77fa6c 0x24e86d 0x18d7966 0x18d7407 0x183a7c0 0x1839db4 0x1839ccb 0x1f8b879 0x1f8b93e 0x585a9b 0xb904d 0x2c75)
terminate called throwing an exceptionCurrent language:  auto; currently objective-c

一个简单的解决方法是将接口构建器连接指向UITableViewCell而不是文件的所有者:

  1. 右键单击File's Owner调出连接列表
  2. 用Command-Shift-4进行屏幕捕捉(拖动以选择要捕捉的区域)
  3. x输出来自文件所有者的连接
  4. 右键单击对象层次结构中的UITableCell并重新添加连接。

正确的方法是创建一个UITableViewCell子类实现、header和XIB。在XIB中删除所有视图,只添加一个表单元格。将类设置为UITableViewCell子类的名称。对于文件所有者,使其为UITableViewController子类类名。使用tableViewCell出口将文件所有者连接到单元格。

在头文件中:

UITableViewCell *_tableViewCell;
@property (assign) IBOutlet UITableViewCell *tableViewCell;

在实现文件中:

@synthesize tableViewCell = _tableViewCell;


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *kCellIdentifier = @"reusableCell";


UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellIdentifier];
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:kCellIdentifier owner:self options:nil];
cell = _tableViewCell;
self.tableViewCell = nil;
}


return cell;
}

正确的解决方法是:

- (void)viewDidLoad
{
[super viewDidLoad];
UINib *nib = [UINib nibWithNibName:@"ItemCell" bundle:nil];
[[self tableView] registerNib:nib forCellReuseIdentifier:@"ItemCell"];
}


-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Create an instance of ItemCell
PointsItemCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ItemCell"];


return cell;
}

检查这个- http://eppz.eu/blog/custom-uitableview-cell/ -非常方便地使用一个在控制器实现中结束一行的小类:

-(UITableViewCell*)tableView:(UITableView*) tableView cellForRowAtIndexPath:(NSIndexPath*) indexPath
{
return [TCItemCell cellForTableView:tableView
atIndexPath:indexPath
withModelSource:self];
}

enter image description here

我决定发帖,因为我不喜欢这些答案——事情总是可以更简单,这是迄今为止我发现的最简洁的方法。

1. 在接口生成器中构建你的Xib,因为你喜欢它

  • 将File's Owner设置为类NSObject
  • 添加一个UITableViewCell,并将它的类设置为MyTableViewCellSubclass——如果你的IB崩溃(在Xcode > 4中发生),只要在Xcode 4中使用一个UIView来做接口,如果你仍然有它在周围
  • 在这个单元格中布局子视图,并将IBOutlet连接以.h或.m(。M是我的首选)

2. 在你的UIViewController或UITableViewController子类中

@implementation ViewController


static NSString *cellIdentifier = @"MyCellIdentier";


- (void) viewDidLoad {


...
[self.tableView registerNib:[UINib nibWithNibName:@"MyTableViewCellSubclass" bundle:nil] forCellReuseIdentifier:cellIdentifier];
}


- (UITableViewCell*) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
MyTableViewCellSubclass *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];


...


return cell;
}

3.在你的mytableviewcell子类中

- (id) initWithCoder:(NSCoder *)aDecoder {
if (self = [super initWithCoder:aDecoder]) {
...
}


return self;
}

首先导入您的自定义单元格文件#import "CustomCell.h",然后更改委托方法,如下所述:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {


static NSString *simpleTableIdentifier = @"CustomCell";


CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:self options:nil];
cell = [nib objectAtIndex:0];


[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
}


return cell;
}
 NSString *CellIdentifier = [NSString stringWithFormat:@"cell %ld %ld",(long)indexPath.row,(long)indexPath.section];




NewsFeedCell *cell = (NewsFeedCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell=nil;


if (cell == nil)
{
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"NewsFeedCell" owner:nil options:nil];


for(id currentObject in topLevelObjects)
{
if([currentObject isKindOfClass:[NewsFeedCell class]])
{
cell = (NewsFeedCell *)currentObject;
break;
}
}
}
return cell;

注册

在iOS 7之后,这个过程被简化为(斯威夫特3.0):

// For registering nib files
tableView.register(UINib(nibName: "MyCell", bundle: Bundle.main), forCellReuseIdentifier: "cell")


// For registering classes
tableView.register(MyCellClass.self, forCellReuseIdentifier: "cell")
这也可以通过在.xib.stroyboard文件中创建单元格作为原型单元格来实现。 如果你需要给它们附加一个类,你可以选择单元格原型并添加相应的类(当然必须是UITableViewCell的后代)

出列

然后,使用(斯威夫特3.0)退出队列:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell : UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)


cell.textLabel?.text = "Hello"


return cell
}

不同之处在于,这个新方法不仅解除了单元格的队列,它还创建了不存在的单元格(这意味着你不必做if (cell == nil)恶作剧),并且单元格已经准备好使用了,就像上面的例子中那样。

(警告) tableView.dequeueReusableCell(withIdentifier:for:)有新的行为,如果你调用另一个(没有indexPath:),你会得到旧的行为,其中你需要检查nil并自己实例它,注意UITableViewCell?返回值。

if let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as? MyCellClass
{
// Cell be casted properly
cell.myCustomProperty = true
}
else
{
// Wrong type? Wrong identifier?
}

当然,单元格的相关类的类型是您在.xib文件中为UITableViewCell子类定义的类型,或者使用另一种寄存器方法。

配置

理想情况下,您的单元格在注册时已经根据外观和内容定位(如标签和图像视图)进行了配置,并且在cellForRowAtIndexPath方法中只需填写它们。

在一起

class MyCell : UITableViewCell
{
// Can be either created manually, or loaded from a nib with prototypes
@IBOutlet weak var labelSomething : UILabel? = nil
}


class MasterViewController: UITableViewController
{
var data = ["Hello", "World", "Kinda", "Cliche", "Though"]


// Register
override func viewDidLoad()
{
super.viewDidLoad()


tableView.register(MyCell.self, forCellReuseIdentifier: "mycell")
// or the nib alternative
}


override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return data.count
}


// Dequeue
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "mycell", for: indexPath) as! MyCell


cell.labelSomething?.text = data[indexPath.row]


return cell
}
}

当然,这些在ObjC中都有相同的名字。

这个扩展需要Xcode7 beta6

extension NSBundle {
enum LoadViewError: ErrorType {
case ExpectedXibToExistButGotNil
case ExpectedXibToContainJustOneButGotDifferentNumberOfObjects
case XibReturnedWrongType
}


func loadView<T>(name: String) throws -> T {
let topLevelObjects: [AnyObject]! = loadNibNamed(name, owner: self, options: nil)
if topLevelObjects == nil {
throw LoadViewError.ExpectedXibToExistButGotNil
}
if topLevelObjects.count != 1 {
throw LoadViewError.ExpectedXibToContainJustOneButGotDifferentNumberOfObjects
}
let firstObject: AnyObject! = topLevelObjects.first
guard let result = firstObject as? T else {
throw LoadViewError.XibReturnedWrongType
}
return result
}
}

创建一个只包含1个自定义UITableViewCell的Xib文件。

加载它。

let cell: BacteriaCell = try NSBundle.mainBundle().loadView("BacteriaCell")

正确的解是这样的

- (void)viewDidLoad
{
[super viewDidLoad];
[self.tableView registerNib:[UINib nibWithNibName:@"CustomCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:@"CustomCell"];
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell  *cell = [tableView dequeueReusableCellWithIdentifier:@"CustomCell"];
return cell;
}

下面是在UITableView中注册单元格的通用方法:

protocol Reusable {
static var reuseID: String { get }
}


extension Reusable {
static var reuseID: String {
return String(describing: self)
}
}


extension UITableViewCell: Reusable { }


extension UITableView {


func register<T: UITableViewCell>(cellClass: T.Type = T.self) {
let bundle = Bundle(for: cellClass.self)
if bundle.path(forResource: cellClass.reuseID, ofType: "nib") != nil {
let nib = UINib(nibName: cellClass.reuseID, bundle: bundle)
register(nib, forCellReuseIdentifier: cellClass.reuseID)
} else {
register(cellClass.self, forCellReuseIdentifier: cellClass.reuseID)
}
}

解释:

  1. Reusable协议从它的类名生成单元ID。确保遵循约定:cell ID == class name == nib name
  2. UITableViewCell符合Reusable协议。
  3. UITableView扩展抽象了通过nib或类注册单元格的差异。

使用的例子:

override func viewDidLoad() {
super.viewDidLoad()
let tableView = UITableView()
let cellClasses: [UITableViewCell.Type] = [PostCell.self, ProfileCell.self, CommentCell.self]
cellClasses.forEach(tableView.register)
}


override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: PostCell.self.reuseID) as? PostCell
...
return cell
}
  1. UITableViewCell创建自己的自定义类AbcViewCell子类(确保你的类文件名和nib文件名是相同的)

  2. 创建这个扩展类方法。

    extension UITableViewCell {
    class func fromNib<T : UITableViewCell>() -> T {
    return Bundle.main.loadNibNamed(String(describing: T.self), owner: nil, options: nil)?[0] as! T
    }
    }
    
  3. Use it.

    let cell: AbcViewCell = UITableViewCell.fromNib()

 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {


let cellReuseIdentifier = "collabCell"
var cell:collabCell! = tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as? collabCell
if cell == nil {
tableView.register(UINib(nibName: "collabCell", bundle: nil), forCellReuseIdentifier: cellReuseIdentifier)
cell = tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as! collabCell!
}




return cell


}

斯威夫特4.2和Xcode 10

我有三个XIB单元格文件

在ViewDidLoad中注册你的XIB文件,像这样…

这是第一种方法

tableView.register(UINib.init(nibName: "XIBCell", bundle: nil), forCellReuseIdentifier: "cell1")
tableView.register(UINib.init(nibName: "XIBCell2", bundle: nil), forCellReuseIdentifier: "cell2")
//tableView.register(UINib.init(nibName: "XIBCell3", bundle: nil), forCellReuseIdentifier: "cell3")

第二种方法是直接在cellForRowAt indexPath:中注册XIB文件

这是我的tableview委托函数

//MARK: - Tableview delegates
override func numberOfSections(in tableView: UITableView) -> Int {


return 1
}


override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {


return 6
}


override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//This is first approach
if indexPath.row == 0 {//Load first XIB cell
let placeCell = tableView.dequeueReusableCell(withIdentifier: "cell1") as! XIBCell
return placeCell
//Second approach
} else if indexPath.row == 5 {//Load XIB cell3
var cell = tableView.dequeueReusableCell(withIdentifier:"cell3") as? XIBCell3
if cell == nil{
let arrNib:Array = Bundle.main.loadNibNamed("XIBCell3",owner: self, options: nil)!
cell = arrNib.first as? XIBCell3
}


//ADD action to XIB cell button
cell?.btn.tag = indexPath.row//Add tag to button
cell?.btn.addTarget(self, action: #selector(self.bookbtn1(_:)), for: .touchUpInside);//selector


return cell!
//This is first approach
} else {//Load XIB cell2
let placeCell = tableView.dequeueReusableCell(withIdentifier: "cell2") as! XIBCell2


return placeCell
}


}