UITableViewCell 为不同的方向和单元格类型加载自定义 XIB
Posted
技术标签:
【中文标题】UITableViewCell 为不同的方向和单元格类型加载自定义 XIB【英文标题】:UITableViewCell loading Custom XIB for different Orientation and Cell Types 【发布时间】:2013-02-19 14:44:14 【问题描述】:我有一个名为 ProductiPadCell
的自定义单元格类,专为 iPad 设计。 (ios 5 SDK)
我想要实现的是根据当前状态(扩展与否)和界面方向加载我的自定义单元格。我在视图控制器中处理这两种情况,问题是我不喜欢它的性能。我NOT为下面定义的任何 xib 定义了一个 cellIdentifier,最近我检测到我的 tableView
的 cellForRowAtIndexPath:
ProductiPadCell
有 4 个不同的 XIB;
ProductiPadCell-Regular.xib
ProductiPadCell-Regular-Landscape.xib
ProductiPadCell-Expanded.xib
ProductiPadCell-Expanded-Landscape.xib
ProductiPadCell 定义;
@interface ProductiPadCell : UITableViewCell
@property (weak, nonatomic) IBOutlet UIButton *detailButton;
@property (weak, nonatomic) IBOutlet UILabel *productDescriptionLabel;
@property (weak, nonatomic) IBOutlet TTTAttributedLabel *timeLabel;
@property (weak, nonatomic) IBOutlet TTTAttributedLabel *def1Label;
@property (weak, nonatomic) IBOutlet TTTAttributedLabel *def2Label;
@property (weak, nonatomic) IBOutlet UIImageView *thumbnail;
// appears in case the cell is expanded
@property (weak, nonatomic) IBOutlet UIView *detailHolderView;
@property (weak, nonatomic) IBOutlet UILabel *detailLabel;
// calls a method at the superview's ViewController
- (void)presentDetailViewWithIndex:(NSInteger)index;
@end
TableView 的 cellForForAtIndexPath
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
// table identifier does not matches the xib's cell identifier
// cell identifier of all 4 xibs are "" (empty)
static NSString *simpleTableIdentifier = @"Cell";
BOOL isExpanded = [[[targetDictionary objectForKey:@"isItemExpanded"] objectAtIndex:indexPath.row] boolValue];
ProductiPadCell *cell = (ProductiPadCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
// Load the required nib for the current orientation and detail selection style
if (deviceOrientation == UIDeviceOrientationPortrait)
if (isExpanded)
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"ProductiPadCell-Regular-Expanded" owner:self options:nil];
cell = [nib objectAtIndex:0];
// additional settings for expanded case
else
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"ProductiPadCell-Regular" owner:self options:nil];
cell = [nib objectAtIndex:0];
// additional settings for NOT expanded case
else
if (isExpanded)
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"ProductiPadCell-Landscape-Expanded" owner:self options:nil];
cell = [nib objectAtIndex:0];
else
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"ProductiPadCell-Regular-Landscape" owner:self options:nil];
cell = [nib objectAtIndex:0];
// connect cell information with cell IBOutlets
cell.productDescriptionLabel.text = [[targetDictionary objectForKey:@"key"] objectAtIndex:indexPath.row];
// ....
[cell.thumbnail setImage:[UIImage imageNamed:@"thumb_image.jpg"]];
[cell.thumbnail.layer setCornerRadius:7.0f];
[cell.thumbnail.layer setBorderWidth:5.0f];
[cell.thumbnail.layer setBorderColor:[UIColor clearColor].CGColor];
[cell.thumbnail setClipsToBounds:YES];
if (isExpanded)
cell.detailLabel.text = [[targetDictionary objectForKey:@"key"] objectAtIndex:indexPath.row];
return cell;
除了我目前的方法之外,我应该怎么做才能加载我的 xib?在每次更改方向和单击按钮时,我都会调用 [tableView reloadData]
并且由于 dequeueReusableCellWithIdentifier:simpleTableIdentifier
没有找到 simpleTableIdentifier,它总是会创建新单元格。如果我将 simpleIdentifier
定义到我的单元格 xib,它们在大小写更改(方向更改、展开状态更改)期间不会更改。
小区标识符的最佳用途是什么?我应该使用dequeueReusableCellWithIdentifier:simpleTableIdentifier
以外的其他方法吗?
我正在等待针对当前情况的任何解决方案,因为我确信一遍又一遍地加载每个单元格并不是最有效的方法。
【问题讨论】:
【参考方案1】:这是一种方式,缓存笔尖
合成这个属性
@property (nonatomic, strong) id cellNib;
@synthesize cellNib = _cellNib;
自定义getter
-(id)cellNib
if (!_cellNib)
Class cls = NSClassFromString(@"UINib");
if ([cls respondsToSelector:@selector(nibWithNibName:bundle:)])
_cellNib = [[cls nibWithNibName:@"SomeCell" bundle:[NSBundle mainBundle]] retain];
return _cellNib;
在 viewDidLoad
[self.tableView registerNib:[UINib nibWithNibName:@"SomeCell" bundle:nil] forCellReuseIdentifier:kCellIdentification];
在 tableView:cellForRowAtIndexPath:
SomeCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellIdentification];
if (cell == nil)
//If nib cache
if ([self cellNib])
NSArray* viewFromNib = [[self cellNib] instantiateWithOwner:self options:nil];
cell = (SomeCell *)[viewFromNib objectAtIndex:0];
else //nib not cache
NSArray *views = [[NSBundle mainBundle] loadNibNamed:@"SomeCell" owner:nil options:nil];
cell = (SomeCell *)[views objectAtIndex:0];
希望有帮助
【讨论】:
只是为了确保我理解正确,对于我的情况,我只有 4 个不同的 cellNib,其中每个都有不同的标识符并在 viewDidLoad 中注册我的所有 4 个 nib(如你所指出的)之后我在 tableView:cellForRowAtIndexPath: 中检查我需要哪个 nib 并使用该标识符调用 dequeueReusableCellWithIdentifier: ?这是我第一次看到 registerNib:forCellReuseIdentifier: 它不常用。谢谢!【参考方案2】:您应该使用新方法 registerNib:forCellReuseIdentifier: 来注册您的笔尖。您对每个 nib 执行一次,在 viewDidLoad 中是一个好地方。每个 nib 中的单元格应该有一个重用标识符,用于注册 nib,并且在出列时也在 cellForRowAtIndexPath 中。在 cellForRowAtIndexPath 中使用的新方法是 dequeueReusableCellWithIdentifier:forIndexPath:。使用该方法,不需要 if (cell == nil) 子句,系统会在必要时从 nib 中创建一个。
【讨论】:
以上是关于UITableViewCell 为不同的方向和单元格类型加载自定义 XIB的主要内容,如果未能解决你的问题,请参考以下文章
强制 UITableViewCell 在方向更改时保持对象右对齐