你如何从Xib文件加载自定义的UITableViewCells?
问题很简单:你如何从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下面测试了上述内容,没有发现内存泄漏。
那么从Xibs加载单元格的规范方法是什么? 我们是否设置文件的所有者? 我们需要工厂吗? 如果是这样,工厂的代码是什么样的? 如果有多种解决方案,让我们来澄清他们每个人的优点和缺点......
原始作者陈述的两种方法是由IB工程师推荐的。
查看实际的帖子了解更多详情。 我更喜欢方法#2,因为它似乎更简单。
方法#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
正确的解决方案是这样的:
- (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;
}
寄存器
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:
tableView.dequeueReusableCell(withIdentifier:for:)
,你会得到旧行为,你需要检查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中都有相同的名称。
链接地址: http://www.djcxy.com/p/78227.html上一篇: How do you load custom UITableViewCells from Xib files?