问题很简单:如何从 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];
}
要使用此代码,请创建 UITableViewCell
的新子类 MyCell.m/.h,并为所需的组件添加 IBOutlets
。然后创建一个新的“空 XIB”文件。在 IB 中打开 Xib 文件,添加一个 UITableViewCell
对象,将其标识符设置为“MyCellIdentifier”,并将其类设置为 MyCell 并添加您的组件。最后,将 IBOutlets
连接到组件。请注意,我们没有在 IB 中设置文件的所有者。
其他方法提倡设置文件的所有者,如果 Xib 没有通过额外的工厂类加载,则会警告内存泄漏。我在 Instruments/Leaks 下测试了上述内容,没有发现内存泄漏。
那么从 Xibs 加载单元的规范方法是什么?我们设置文件的所有者吗?我们需要工厂吗?如果是这样,工厂的代码是什么样的?如果有多种解决方案,让我们澄清每个解决方案的优缺点......
正确的解决方案是这样的:
- (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;
}
以下是 original author states was recommended by an IB engineer 的两种方法。
有关更多详细信息,请参阅实际帖子。我更喜欢方法#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 仍然有效,但不再有相关文档。它曾经在 official docs 中,但现在被删除以支持情节提要。
我在 Github 上发布了一个工作示例:
https://github.com/bentford/NibTableCellExample
为 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
}
登记
在 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)
恶作剧),并且单元格已准备好使用,就像上面的示例一样.
(警告) 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 中都可以使用相同的名称。
[self.tableView registerNib:[UINib nibWithNibName:@"BlaBlaTableViewCell" bundle:nil] forCellReuseIdentifier:kCellIdentifier];
接受了 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"];
我使用了本特福德的方法#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 文件中与文件所有者的连接。
通过在 loadNibNamed
语句中传递 owner:self
,您将 UITableViewController
设置为 UITableViewCell
的文件所有者。
如果你拖放到IB中的头文件来设置动作和出口,它会默认将它们设置为文件的所有者。
在 loadNibNamed:owner:options
中,Apple 的代码将尝试在您的 UITableViewController
上设置属性,因为那是所有者。但是您没有在那里定义这些属性,因此您会收到关于 key value coding-compliant 的错误:
*** 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
一个简单的解决方法是将您的 Interface Builder 连接指向 UITableViewCell
而不是 File's Owner:
右键单击 File's Owner 以拉出连接列表 使用 Command-Shift-4 进行屏幕截图(拖动以选择要捕获的区域) x 从 File's Owner 中删除连接 右键单击对象层次结构中的 UITableCell 并重新-添加连接。
我决定发布,因为我不喜欢这些答案中的任何一个——事情总是更简单,这是迄今为止我发现的最简洁的方式。
1. 根据需要在 Interface Builder 中构建 Xib
将文件的所有者设置为类 NSObject
添加一个 UITableViewCell 并将其类设置为 MyTableViewCellSubclass - 如果您的 IB 崩溃(在撰写本文时发生在 Xcode > 4 中),只需使用 UIView 在 Xcode 4 中执行界面,如果您仍然放置它
将您的子视图布局在此单元格内,并将您的 IBOutlet 连接附加到 .h 或 .m 中的 @interface(.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. 在你的 MyTableViewCellSubclass
- (id) initWithCoder:(NSCoder *)aDecoder {
if (self = [super initWithCoder:aDecoder]) {
...
}
return self;
}
如果您使用 Interface Builder 制作单元格,请检查您是否已在 Inspector 中设置了 Identifier。然后在调用dequeueReusableCellWithIdentifier时检查是否相同。
我不小心忘记在一个繁重的项目中设置一些标识符,性能变化就像白天和黑夜。
从 XIB 加载 UITableViewCells 可以节省大量代码,但通常会导致滚动速度非常糟糕(实际上,不是 XIB 而是过度使用 UIViews 导致了这种情况)。
我建议你看看这个:Link reference
这是我一直用来从 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 中获取视图。
正确的解决方案是这个
- (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;
}
重新加载 NIB 是昂贵的。最好加载一次,然后在需要单元格时实例化对象。请注意,您可以使用此方法将 UIImageViews 等添加到 nib,甚至多个单元格(Apple 的“registerNIB”iOS5 只允许一个顶级对象 - 错误 10580062“iOS5 tableView registerNib:过度限制”
所以我的代码在下面——你在NIB中读过一次(像我一样初始化或在viewDidload中——不管怎样。从那时起,你将笔尖实例化为对象,然后选择你需要的对象。这比加载笔尖效率高得多一遍又一遍。
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;
}
检查这个 - http://eppz.eu/blog/custom-uitableview-cell/ - 使用一个小类的非常方便的方法,它在控制器实现中结束了一行:
-(UITableViewCell*)tableView:(UITableView*) tableView cellForRowAtIndexPath:(NSIndexPath*) indexPath
{
return [TCItemCell cellForTableView:tableView
atIndexPath:indexPath
withModelSource:self];
}
https://i.stack.imgur.com/TZEB3.png
正确的做法是创建一个 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;
}
我为此做的是在您的控制器类中声明一个 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)
从 UITableViewCell 创建您自己的自定义类 AbcViewCell 子类(确保您的类文件名和 nib 文件名相同)创建此扩展类方法。 extension UITableViewCell { class func fromNib
首先导入您的自定义单元文件 #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;
}
在 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
}
}
这是我的方法:Loading Custom UITableViewCells from XIB Files… Yet Another Method
想法是创建 UITableViewCell
的 SampleCell 子类,其中包含 IBOutlet UIView *content
属性和您需要从代码中配置的每个自定义子视图的属性。然后创建一个 SampleCell.xib 文件。在此 nib 文件中,将文件所有者更改为 SampleCell。添加大小适合您需要的内容 UIView
。添加和配置您想要的所有子视图(标签、图像视图、按钮等)。最后,将内容视图和子视图链接到文件所有者。
这是在 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)
}
}
解释:
可重用协议根据其类名生成单元 ID。确保遵循约定:单元 ID == 类名 == 笔尖名称。 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
}
我不知道是否有规范的方法,但这是我的方法:
为 ViewController 创建一个 xib
将文件所有者类设置为 UIViewController
删除视图并添加一个 UITableViewCell
将您的 UITableViewCell 的 Class 设置为您的自定义类
设置你的 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 中项目的顺序,可能会中断。
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;
此扩展需要 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")
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
}