表视图单元属性保持为零

时间:2014-01-23 00:04:58

标签: ios objective-c uitableview

我正在尝试实现this示例项目中显示的概念。我的目标是分离我的视图控制器类和数据源协议。我没有在我的表视图控制器类中实现表视图数据源方法,而是尝试将它放在自己的类中,在我的视图控制器中,我只调用此方法来设置我的表视图:

- (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具有有效属性):

- (void)configureForTodoItem:(JVRTodoItem *)aTodoItem
{
    self.todoItemTitle.text = aTodoItem.title;
    self.todoItemPriority.text = [NSString stringWithFormat:@"%d", aTodoItem.priority];
} 

我想弄清楚这里可能会遗漏什么,但到目前为止,我还没有设法解决这个问题,而我开始失去希望。任何帮助将不胜感激。

更新: 为清楚起见,问题显示在此图片上。

It seems that the cells get created, but its labels don't.

似乎细胞已经创建,但它的标签却没有。

3 个答案:

答案 0 :(得分:1)

如果您只想将tableview数据源委托与视图控制器分开,则可以创建一个名为TableViewDataSource的单独类。在该类中,您可以管理数据源及其表视图单元格;在视图控制器中配置它们,但让TableViewDataSource管理它们。

<强> TDSTableViewDataSource.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

<强> TableViewDataSource.m

#import "TDSTableViewDataSource.h"

@implementation TDSTableViewDataSource

- (NSArray *)items {
    if (!_items) _items = [[NSArray alloc] init];
    return _items;
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    if ([self.items count]) {
        return [self.items count];
    } else {
        NSLog(@"numberOfSectionsInTableView could not be determined. self.items is nil or empty.");
        return 0;
    }
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    if ([self.items count]) {
        return [self.items count];
    } else {
        NSLog(@"numberOfRowsInSection could not be determined. self.items contains fewer section requested does not contain any items.");
        return 0;
    }
}

/*
 Single dimension Array of items belonging to a UITableView section

 The method checks if the cell implements the HZConfigureTableViewCellDelegate, which is required.
 The delegate should be the View Controller.
 */
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    id obj = [self.items objectAtIndex:indexPath.row];
    UITableViewCell *cell = nil;

    if ([self.delegate conformsToProtocol:@protocol(TDSTableViewDataSourceDelegate)]) {
        NSString *cellIdentifier = [self.delegate fetchCellIdentifierForObject:obj];
        cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

        if (obj)
            cell = [self.delegate configureCell:cell usingObject:obj];
    }

    return cell;
}

@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

这是一个完整的示例项目。您可以使用它来配置所需的任何类型的单元格,而无需将数据源方法添加到视图控制器。

ConfigureTableViewCellDelegate协议使用视图控制器来配置UITableViewCell并在表视图中使用它们。由于代码现在是隔离的,TableViewDataSource类现在处理将数据呈现给表视图。 View Controller仅用于配置单元。如果需要,这允许您在每个ViewController上使用自定义UITableViewCells,而不必每次都处理实现数据源。

<强>已更新

提供了一个更好的例子,一个完整的项目模板。

答案 1 :(得分:1)

在ViewDidLoad注册nib中,它解决了问题:)

  -(void)viewDidLoad
    {
         [self.leftTableView registerNib:[UINib nibWithNibName:NIB_FILE bundle:nil] forCellReuseIdentifier:CELL_IDENTIFIER];
    }

答案 2 :(得分:0)

经过几个小时的挖掘,我设法解决了这个问题(现在),将自定义单元的出口更改为强属性,并在单元的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;
}

这很奇怪,因为我认为在故事板中创建我的观点,这应该自动处理,我从来没有必须手动执行此操作。