将 UITableViewDataSource 与具有子视图的自定义单元格一起使用
Posted
技术标签:
【中文标题】将 UITableViewDataSource 与具有子视图的自定义单元格一起使用【英文标题】:Using UITableViewDataSource with Custom Cells Having Subviews 【发布时间】:2015-12-30 06:31:57 【问题描述】:在 UITableView 中使用自定义单元格时,我得到一个奇怪的表格重叠:
问题
向下滚动并在最后两行上涂上前两行! 向上滚动,前两行在上面画了两行!这是 UITableViewDataSource 的代码:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
let cell : UITableViewCell = tableView.dequeueReusableCellWithIdentifier("cell") as UITableViewCell!;
let cellText:String = self.items[indexPath.row];
let subjectField:UILabel = UILabel(frame: CGRect(x:55, y: 25, width: 303, height: 25));
subjectField.text = cellText;
//cell.textLabel?.text = cellText; //works fine!
cell.addSubview(subjectField); //fails XX(!
return cell;
这是截图:
注意:“0 9”和“1 A”是涂装! Ref:'0 9' 是 row#0 ('0') 和 row#9 ('9')问题
为什么添加子视图会导致绘制问题? 将自定义视图绘制到单元格中的正确方法是什么?上下文
我的实际原始代码在自定义表格视图中使用自定义单元格 此处的代码示例是原始代码的精简版本。我可以发布任何需要帮助解决此问题的内容!【问题讨论】:
我发现您的代码存在两个明显的问题:1)dequeueReusableCellWithIdentifier:
可能返回 null,因此您需要创建一个新的单元格实例。您最好使用dequeueReusableCellWithIdentifier:forIndexPath:
,它会在需要时自动分配单元格,并且2)您在重用单元格时一次又一次地添加subjectField
子视图。您应该在 XIB 中添加一次,或者检查它是否已经添加到您的代码中。
【参考方案1】:
单元格标识符的问题必须是唯一的
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
let cellId:String = "Cell"+String(indexPath.row)
var cell = tableView.dequeueReusableCellWithIdentifier(cellId)
if (cell == nil)
cell = UITableViewCell(style: .Default, reuseIdentifier:cellId)
let cellText:String = String(indexPath.row)
let subjectField:UILabel = UILabel(frame: CGRect(x:55, y: 25, width: 303, height: 25))
subjectField.text = cellText
(cell! as UITableViewCell).addSubview(subjectField)
return cell! as UITableViewCell
【讨论】:
我吃了一惊,印象深刻和惊讶 - 你修好了!!!!!!!!!!!! (cell == nil) 是关键。感谢您在这里交流问题的根源,然后是解决方案!!!!度过了我的夜晚,谢谢!!!! :)【参考方案2】:头晕目眩 , 创建自定义单元格并在运行时以及从 Xib 中使用 Control。
1) 在 Xib 或 Storyboard 中的 ViewController 中创建 CustomCell。
2) 为您的单元格提供标识符
3) 在tableview的cellForRowAtIndexpath数据源方法中添加以下代码
static NSString *cellId = @"CustomIdenfier";
CustomCell *cell = (CustomCell*)[tableView dequeueReusableCellWithIdentifier:firstCellId];
if (cell == nil)
cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
[self createCustomCell:cell atIndexPath:indexPath];
[self updateCustomCell:cell atIndexPath:indexPath];
return cell;
4) createCustomCell 方法如果在 Xib 中添加控件则不需要此方法
-(void)createCustomCell:(CustomCell*)cell atIndexPath:(NSIndexPath*)indexPath
//Here I am adding custom label run time, you can add
// Any control in Xib and create a reference IBOutlet for it and user here.
UILabel *lblTitle = [[UILabel alloc] initWithFrame:CGRectMake(5, 5, cell.contentView.frame.size.width-10, 30)];
lblTitle.textColor = [UIColor blackColor];
lblTitle.tag = 1;
[cell.contentView addSubview:lblTitle];
5) updateCustomCell 方法
-(void)updateCustomCell:(CustomCell*)cell atIndexPath:(NSIndexPath*)indexPath
UILabel *lblTitle = (UILabel*)[cell.contentView viewWithTag:1];
[lblTitle setText:[NSString stringWithFormat:@"%i",indexPath.row]];
//编辑1 如果不使用 Storyboard,则创建 UITableviewCell 的自定义扩展。
//CustomCell.h
#import <UIKit/UIKit.h>
@interface CustomCell : UITableViewCell
@property (strong, nonatomic) UILabel *lblTitle;
@end
//CustomCell.m
#import "CustomCell.h"
@implementation CustomCell
@synthesize lblTitle;
- (void)awakeFromNib
NSLog(@"imgUrl:%@ txtName:%@",imgUser,txtName);
// Initialization code
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(nullable NSString *)reuseIdentifier
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if(self)
//Setup your Cell like initialising variables and setting frames of controls
return self;
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
[super setSelected:selected animated:animated];
// Configure the view for the selected state
@end
【讨论】:
我不使用情节提要。我是 100% 程序化的,对不起!谢谢你的详细回答!!! J-Dizzle,为以编程方式使用自定义单元格而编辑。【参考方案3】:根据 Rajesh Balam 的回答,这里是我的 UITableViewDataSource 中我的原始代码的工作形式!
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
/**********************************************************/
/* @soln a UNIQUE 'cellId' is the key */
/**********************************************************/
let cellId :String = "Cell" + String(indexPath.row);
var cell : UITableViewCell? = tableView.dequeueReusableCellWithIdentifier(cellId);
if (cell == nil)
cell = UITableViewCell(style: .Default, reuseIdentifier:cellId); //comment this out and watch it fail!
let cellText:String = self.items[indexPath.row];
let subjectField:UILabel = UILabel(frame: CGRect(x:55, y: 25, width: 303, height: 25));
subjectField.text = cellText;
(cell! as UITableViewCell).addSubview(subjectField);
return cell! as UITableViewCell;
它有效。谢谢拉杰什!!! :)
【讨论】:
以上是关于将 UITableViewDataSource 与具有子视图的自定义单元格一起使用的主要内容,如果未能解决你的问题,请参考以下文章
“TableViewController”与协议“UITableViewDataSource”的冗余一致性[重复]
分离 UITableViewDelegate 和 UITableViewDataSource 导致没有数据显示
无法调用 UITableViewDataSource 方法,调试时即使光标也无法进入这些方法
制作 UITableViewDataSource 的主视图控制器委托