Ios 表视图单元格属性保持为零
我试图实现示例项目中所示的概念。我的目标是分离视图控制器类和数据源协议。我没有在我的表视图控制器类中实现表视图数据源方法,而是尝试将其放在自己的类中,在我的视图控制器中,我只调用此方法来设置我的表视图:Ios 表视图单元格属性保持为零,ios,objective-c,uitableview,Ios,Objective C,Uitableview,我试图实现示例项目中所示的概念。我的目标是分离视图控制器类和数据源协议。我没有在我的表视图控制器类中实现表视图数据源方法,而是尝试将其放在自己的类中,在我的视图控制器中,我只调用此方法来设置我的表视图: - (void)setupTableView { void (^configureCell)(JVRTodoItemCell *, JVRTodoItem *) = ^(JVRTodoItemCell *cell, JVRTodoItem *todoItem) {
- (void)setupTableView
{
void (^configureCell)(JVRTodoItemCell *, JVRTodoItem *) = ^(JVRTodoItemCell *cell, JVRTodoItem *todoItem)
{
[cell configureForTodoItem:todoItem];
};
NSArray *todoItems = currentUser.todoItems;
self.todoArrayDataSource = [[JVRArrayDataSource alloc] initWithItems:todoItems withCellIdentifier:TodoCellIdentifier withConfigureCellBlock:configureCell];
self.tableView.dataSource = self.todoArrayDataSource;
[self.tableView registerClass:[JVRTodoItemCell class] forCellReuseIdentifier:TodoCellIdentifier];
}
数据源被划分为自己的类:
@interface JVRArrayDataSource ()
@property (copy,nonatomic) NSArray *items;
@property (copy,nonatomic) NSString *cellIdentifier;
@property (copy,nonatomic) void (^configureCellBlock)(id item, id cell);
@end
@implementation JVRArrayDataSource
...
#pragma mark - UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.items.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:self.cellIdentifier forIndexPath:indexPath];
id item = [self itemAtIndexPath:indexPath];
self.configureCellBlock(cell,item);
return cell;
}
有趣的是,基于标识符(使用dequeueReusableCellWithIdentifier:forIndexPath:)创建单元格似乎是成功的,因为分配了正确的单元格,但其标签保持为零。我尝试使用以下方法设置单元格,但值仍然为零(aTodoItem具有有效属性):
我正试图找出这里可能缺少什么,但到目前为止,我还没有设法解决这个问题,我开始失去希望。任何帮助都将不胜感激
更新:
为了清楚起见,这张图片上显示了这个问题
单元格似乎已创建,但其标签未创建。如果您只想将tableview数据源委托与视图控制器分离,则可以创建一个名为
TableViewDataSource
的单独类。在该类中,您可以管理数据源及其表视图单元格;在视图控制器中配置它们,但让TableViewDataSource
管理它们
tdstablevewdatasource.h
#import <Foundation/Foundation.h>
@protocol TDSTableViewDataSourceDelegate <NSObject>
- (NSString *)fetchCellIdentifierForObject:(id)object;
- (UITableViewCell *)configureCell:(UITableViewCell *)cell usingObject:(id)item;
@end
@interface TDSTableViewDataSource : NSObject <UITableViewDataSource>
@property (strong, nonatomic) NSArray *items;
@property (strong, nonatomic) id<TDSTableViewDataSourceDelegate> delegate;
@end
该类和协议基本上允许您获取和配置UITableViewCell
,而不必在视图控制器中实现协议
在视图控制器内,使用上述协议创建数据源属性
#import "TDSViewController.h"
#import "TDSTableViewDataSource.h"
@interface TDSViewController () <UITableViewDelegate, TDSTableViewDataSourceDelegate>
@property (strong, nonatomic) TDSTableViewDataSource *dataSource; // UITableView data source.
@property (weak, nonatomic) IBOutlet UITableView *tableView;
@end
@implementation TDSViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.tableView.dataSource = self.dataSource;
self.dataSource.delegate = self;
}
#pragma mark - UITableView methods
-(NSString *)fetchCellIdentifierForObject:(id)object {
// Check if this is an event or a Reminder class.
if ([object isKindOfClass:[UITableViewCell class]]) {
// Return the cell identifier for this particular cell.
return @"com.myapp.defaultcell";
}
return @"blankcell";
}
- (UITableViewCell *)configureCell:(UITableViewCell *)cell usingObject:(id)item {
UITableViewCell *configuredCell = cell;
// Check if this is an event or a reminder.
if ([item isKindOfClass:[UITableViewCell class]]) {
// Configure the cell to present what data we want here...
}
return configuredCell;
}
@end
#导入“TDSViewController.h”
#导入“TDSTableViewDataSource.h”
@接口TDSViewController()
@属性(强,非原子)TDSTableViewDataSource*数据源;//UITableView数据源。
@属性(弱、非原子)IBUITableView*tableView;
@结束
@TDSViewController的实现
-(无效)viewDidLoad
{
[超级视图下载];
self.tableView.dataSource=self.dataSource;
self.dataSource.delegate=self;
}
#pragma标记-UITableView方法
-(NSString*)fetchCellIdentifierForObject:(id)对象{
//检查这是一个事件还是一个提醒类。
if([object IsKindof类:[UITableViewCell类]]){
//返回此特定单元格的单元格标识符。
返回@“com.myapp.defaultcell”;
}
返回@“空白单元格”;
}
-(UITableViewCell*)配置单元格:(UITableViewCell*)使用对象的单元格:(id)项{
UITableViewCell*configuredCell=单元格;
//检查这是一个事件还是一个提醒。
if([项是类的种类:[UITableViewCell类]]){
//配置单元格以显示我们需要的数据。。。
}
返回配置的小区;
}
@结束
这是一个完整的示例项目。您可以使用它来配置任何类型的单元格,而无需将数据源方法添加到视图控制器中
视图控制器由ConfigureTableViewCellDelegate
协议用于配置UITableViewCell
,并在表视图中使用它们。由于代码现在是隔离的,因此TableViewDataSource
类现在处理向表视图显示数据的操作。视图控制器仅用于配置单元的。这允许您在每个ViewController上使用自定义UITableViewCells(如果需要),而不必每次都实现数据源
已更新
提供了一个更好的示例,一个完整的项目模板。经过数小时的挖掘,我已经设法解决了这个问题(目前),方法是将自定义单元格的outlet更改为强属性,并在单元格的init方法中初始化它们:
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
self.todoItemTitle = [[UILabel alloc] init];
self.todoItemPriority = [[UILabel alloc] init];
}
return self;
}
这是非常奇怪的,因为我认为在故事板中创建视图应该自动处理,而且我以前从未手动执行过此操作。在ViewDidLoad中注册nib,它解决了问题:)
我看不到您在哪里调用
configureForTodoItem:
。此外,我不知道您试图对创建cell
和返回cell
之间的两行执行什么操作。configureForTodoItem:从视图控制器(在configureCell块中)调用。创建单元格后,我查看相应行中的条目,并调用configure方法为该条目的属性设置单元格标签?我一点也不明白这些代码在做什么。你想完成什么?很抱歉不清楚,我会试着编辑这篇文章。setupTableView是从我的表视图控制器调用的。目标主要是在一个单独的类中实现一个更通用的数据源协议。我想我只是不明白为什么。tableview所在的视图控制器、tableview委托和tableview数据源都可以是它们自己的类,而不需要任何额外的工作、抽象或混淆。听起来你好像在为一个数据源编写一个数据源。Johnathon,谢谢你的详细回答,这是一个很好的例子。我的问题让我感到困扰的是,我的表视图单元格没有被创建,尽管我认为我的方法是正确的。但是有一个问题:TDSTableViewDataSource类拥有对TDSViewController的强引用,反之亦然,这不是很糟糕吗?老实说,我不确定。我想,对VC的引用可能很弱,只是从VC强烈引用了它。是的,还有其他一些错误。您不应该将UITableViewCell视图设置为强视图。它已经被单元格强烈引用。您正在将这些插座添加到标题中,对吗?是的,它们位于标题中,并连接到相应的情节提要对象,但它们没有
#import "TDSViewController.h"
#import "TDSTableViewDataSource.h"
@interface TDSViewController () <UITableViewDelegate, TDSTableViewDataSourceDelegate>
@property (strong, nonatomic) TDSTableViewDataSource *dataSource; // UITableView data source.
@property (weak, nonatomic) IBOutlet UITableView *tableView;
@end
@implementation TDSViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.tableView.dataSource = self.dataSource;
self.dataSource.delegate = self;
}
#pragma mark - UITableView methods
-(NSString *)fetchCellIdentifierForObject:(id)object {
// Check if this is an event or a Reminder class.
if ([object isKindOfClass:[UITableViewCell class]]) {
// Return the cell identifier for this particular cell.
return @"com.myapp.defaultcell";
}
return @"blankcell";
}
- (UITableViewCell *)configureCell:(UITableViewCell *)cell usingObject:(id)item {
UITableViewCell *configuredCell = cell;
// Check if this is an event or a reminder.
if ([item isKindOfClass:[UITableViewCell class]]) {
// Configure the cell to present what data we want here...
}
return configuredCell;
}
@end
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
self.todoItemTitle = [[UILabel alloc] init];
self.todoItemPriority = [[UILabel alloc] init];
}
return self;
}
-(void)viewDidLoad
{
[self.leftTableView registerNib:[UINib nibWithNibName:NIB_FILE bundle:nil] forCellReuseIdentifier:CELL_IDENTIFIER];
}