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];
    }