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

本文翻译自:How do you load custom UITableViewCells from Xib files?

The question is simple: How do you load custom UITableViewCell from Xib files? 问题很简单:如何从Xib文件加载自定义UITableViewCell Doing so allows you to use Interface Builder to design your cells. 这样做允许您使用Interface Builder来设计单元格。 The answer apparently is not simple due to memory managment issues. 由于内存管理问题,答案显然并不简单。 This thread mentions the issue and suggests a solution, but is pre NDA-release and lacks code. 这个主题提到了这个问题并建议了一个解决方案,但是在NDA发布之前并且没有代码。 Here's a long thread that discusses the issue without providing a definitive answer. 这是一个很长的线程 ,在没有提供明确答案的情况下讨论了这个问题。

Here's some code I've used: 这是我用过的一些代码:

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];
}

To use this code, create MyCell.m/.h, a new subclass of UITableViewCell and add IBOutlets for the components you want. 要使用此代码,请创建MyCell.m / .h, UITableViewCell的新子类,并为所需的组件添加IBOutlets Then create a new "Empty XIB" file. 然后创建一个新的“空XIB”文件。 Open the Xib file in IB, add a UITableViewCell object, set its identifier to "MyCellIdentifier", and set its class to MyCell and add your components. 在IB中打开Xib文件,添加UITableViewCell对象,将其标识符设置为“MyCellIdentifier”,并将其类设置为MyCell并添加组件。 Finally, connect the IBOutlets to the components. 最后,将IBOutlets连接到组件。 Note that we did not set the File's Owner in IB. 请注意,我们没有在IB中设置文件所有者。

Other methods advocate setting the File's Owner and warn of memory leaks if the Xib is not loaded via an additional factory class. 如果未通过其他工厂类加载Xib,则其他方法主张设置文件所有者并警告内存泄漏。 I tested the above under Instruments/Leaks and saw no memory leaks. 我在Instruments / Leaks下测试了上面的内容,没有发现内存泄漏。

So what's the canonical way to load cells from Xibs? 那么从Xibs加载单元格的规范方法是什么? Do we set File's Owner? 我们设置文件的所有者吗? Do we need a factory? 我们需要工厂吗? If so, what's the code for the factory look like? 如果是这样,工厂的代码是什么样的? If there are multiple solutions, let's clarify the pros and cons of each of them... 如果有多种解决方案,让我们澄清每种解决方案的优缺点......


#1楼

参考:https://stackoom.com/question/2gzf/如何从Xib文件加载自定义UITableViewCells


#2楼

The correct way to do it is to create a UITableViewCell subclass implementation, header, and XIB. 正确的方法是创建UITableViewCell子类实现,标头和XIB。 In the XIB remove any views and just add a table cell. 在XIB中删除任何视图,只需添加一个表格单元格。 Set the class as the name of the UITableViewCell subclass. 将类设置为UITableViewCell子类的名称。 For file owner, make it the UITableViewController subclass class name. 对于文件所有者,使其成为UITableViewController子类的类名。 Connect the file owner to the cell using the tableViewCell outlet. 使用tableViewCell插座将文件所有者连接到单元。

In the header file: 在头文件中:

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

In the implementation file: 在实现文件中:

@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;
}

#3楼

The right solution is this: 正确的解决方案是:

- (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楼

Check this - http://eppz.eu/blog/custom-uitableview-cell/ - really convenient way using a tiny class that ends up one line in controller implementation: 检查一下 - http://eppz.eu/blog/custom-uitableview-cell/ - 使用一个在控制器实现中结束一行的小类非常方便的方法:

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

在此输入图像描述


#5楼

I've decided to post since I don't like any of these answers -- things can always be more simple and this is by far the most concise way I've found. 我决定发帖,因为我不喜欢任何这些答案 - 事情总是更简单,这是迄今为止我发现的最简洁的方式。

1. Build your Xib in Interface Builder as you like it 1.根据需要在Interface Builder中构建Xib

  • Set File's Owner to class NSObject 将File的Owner设置为NSObject类
  • Add a UITableViewCell and set its class to MyTableViewCellSubclass -- if your IB crashes (happens in Xcode > 4 as of this writing), just use a UIView of do the interface in Xcode 4 if you still have it laying around 添加一个UITableViewCell并将其类设置为MyTableViewCellSubclass - 如果您的IB崩溃(在撰写本文时Xcode> 4中发生),只需使用UIView在Xcode 4中执行该接口,如果您仍然存在它
  • Layout your subviews inside this cell and attach your IBOutlet connections to your @interface in the .h or .m (.m is my preference) 在此单元格内布置子视图,并将您的IBOutlet连接附加到.h或.m中的@interface(.m是我的偏好)

2. In your UIViewController or UITableViewController subclass 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. In your MyTableViewCellSubclass 3.在MyTableViewCellSubclass中

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

    return self;
}

#6楼

Here are two methods which the original author states was recommended by an IB engineer . 以下是IB工程师推荐的两种原始作者所述的方法。

See the actual post for more details. 有关详细信息,请参阅实际帖子。 I prefer method #2 as it seems simpler. 我更喜欢方法#2,因为它似乎更简单。

Method #1: 方法#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: 方法#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): Method #2 is still valid but there is no documentation for it anymore. 更新(2014):方法#2仍然有效,但不再有文档。 It used to be in the official docs but is now removed in favor of storyboards. 它曾经在官方文档中,但现在被删除,有利于故事板。

I posted a working example on Github: 我在Github上发布了一个工作示例:
https://github.com/bentford/NibTableCellExample https://github.com/bentford/NibTableCellExample

edit for Swift 4.2 编辑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
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值