首页 文章

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

提问于
浏览
282

问题很简单:如何从Xib文件加载自定义 UITableViewCell ?这样做允许您使用Interface Builder来设计单元格 . 由于内存管理问题,答案显然并不简单 . This thread提到了这个问题并建议了一个解决方案,但是在NDA发布之前并且没有代码 . 这是一个long thread,在没有提供明确答案的情况下讨论了这个问题 .

这是我用过的一些代码:

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下测试了上面的内容,没有发现内存泄漏 .

那么从Xibs加载单元格的规范方法是什么?我们设置文件所有者吗?我们需要工厂吗?如果是这样,工厂的代码是什么样的?如果有多种解决方案,让我们澄清每种解决方案的优缺点......

23 回答

  • 13

    这里有两种方法original author states was recommended by an IB engineer .

    有关详细信息,请参阅实际帖子 . 我更喜欢方法#2,因为它似乎更简单 .

    Method #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;
    }
    

    Method #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;
    }
    

    Update (2014): 方法#2仍然有效,但不再有文档了 . 它曾经在official docs但现在被删除,有利于故事板 .

    我在Github上发布了一个工作示例:
    https://github.com/bentford/NibTableCellExample

  • 0

    正确的解决方案是:

    - (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;
    }
    
  • 4

    注册

    在iOS 7之后,此过程已简化为( swift 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的后代) .

    出队

    然后,使用( swift 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) shenanigans),并且单元格已准备就绪,就像上面的示例一样 .

    (警告)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中都有相同的名称 .

  • 6

    拿起Shawn Craver的回答并清理了一下 .

    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"];
    
  • 3

    我用过bentford的 Method #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;
    }
    

    It works, but watch out for connections to File's Owner in your custom UITableViewCell .xib file.

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

    如果拖放到IB中的头文件以设置操作和出口,默认情况下会将其设置为文件所有者 .

    loadNibNamed:owner:options 中,Apple的代码将尝试在 UITableViewController 上设置属性,因为's the owner. But you don' t具有在那里定义的那些属性,因此您会收到关于符合键值编码的错误:

    *** 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
    

    An easy workaround is to point your Interface Builder connections at the UITableViewCell instead of File's Owner:

    • 右键单击文件所有者以提取连接列表

    • 使用Command-Shift-4进行屏幕捕获(拖动以选择要捕获的区域)

    • x了文件所有者的连接

    • 右键单击Object层次结构中的UITableCell并重新添加连接 .

  • 4

    我决定发帖,因为我不喜欢任何这些答案 - 事情总是更简单,这是迄今为止我发现的最简洁的方式 .

    1. Build your Xib in Interface Builder as you like it

    • 将文件所有者设置为类NSObject

    • 添加UITableViewCell并将其类设置为MyTableViewCellSubclass - 如果您的IB崩溃(在撰写本文时发生在Xcode> 4中),只需使用UIView在Xcode 4中执行该接口,如果您仍然存在它

    • 在此单元格内布置子视图,并将您的IBOutlet连接附加到.h或.m中的@interface(.m是我的偏好)

    2. In your UIViewController or UITableViewController subclass

    @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. In your MyTableViewCellSubclass

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

    如果您正在使用Interface Builder制作单元格,检查您是否在检查器中设置了标识符 . 然后在调用dequeueReusableCellWithIdentifier时检查它是否相同 .

    我不小心忘了在一个表格繁重的项目中设置一些标识符,性能变化就像是白天和黑夜 .

  • 5

    从XIB加载UITableViewCells可以节省大量代码,但通常会导致可怕的滚动速度(实际上,它不是XIB,而是过度使用导致此问题的UIViews) .

    我建议你看看这个:Link reference

  • 1

    这是我用来从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更可靠's example because you'保证只能从XIB中获取正确类型的视图 .

  • 9

    正确的解决方案就是这样

    - (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; 
        }
    
  • 2

    重新加载NIB是昂贵的 . 最好加载一次,然后在需要单元格时实例化对象 . 请注意,您可以使用此方法将UIImageViews等添加到nib,甚至是多个单元格(Apple的“registerNIB”iOS5只允许一个顶级对象 - Bug 10580062“iOS5 tableView registerNib:过度限制”

    所以我的代码在下面 - 你在NIB中读过一次(在初始化时像我一样或在viewDidload中 - 无论如何 . 从那时起,你将nib实例化为对象然后选择你需要的那个 . 这比加载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;
    }
    
  • 33

    检查一下 - 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

    正确的方法是创建UITableViewCell子类实现,标头和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;
    }
    
  • 8

    我为此做的是在你的控制器类中声明一个 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 additions loadNibNamed (ADC login)

    cocoawithlove.com article I sourced the concept from (get the phone numbers sample app)

  • 3

    首先导入自定义单元格文件 #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;
    }
    
  • 0

    这是我的方法:Loading Custom UITableViewCells from XIB Files… Yet Another Method

    我们的想法是创建 UITableViewCell 的SampleCell子类,其中包含 IBOutlet UIView *content 属性以及您需要从代码配置的每个自定义子视图的属性 . 然后创建SampleCell.xib文件 . 在此nib文件中,将文件所有者更改为SampleCell . 添加内容 UIView 大小以满足您的需求 . 添加和配置所需的所有子视图(标签,图像视图,按钮等) . 最后,将内容视图和子视图链接到文件所有者 .

  • 0
    • UITableViewCell 创建自己的自定义类 AbcViewCell 子类(确保您的类文件名和nib文件名相同)

    • 创建此扩展类方法 .

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

    let cell: AbcViewCell = UITableViewCell.fromNib()

  • 296

    我不知道是否有规范的方法,但这是我的方法:

    • 为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]
    

    如果Apple更改了xib中项目的顺序,可能会中断 .

  • 0
    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;
    
  • 0

    此扩展需要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")
    
  • 38

    以下是在 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)
        }
    }
    

    说明:

    • Reusable 协议从其类名生成单元ID . 确保遵循惯例: cell ID == class name == nib name .

    • UITableViewCell 符合 Reusable 协议 .

    • 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
    }
    
  • 16
    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
    
    }
    
  • 286

    Swift 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
        }
    
    }
    

相关问题