2014-01-23 5 views
1

Я пытаюсь реализовать концепцию, показанную в примере проекта this. Моя цель - отделить класс контроллера вида и протокол данных. Вместо реализации методов DATASOURCE просмотра таблицы в моей таблице класса контроллера представления, я пытаюсь поставить его в своем классе, и на мой взгляд, контроллер, я только называю этот метод, чтобы настроить мой вид таблицы:Свойства ячейки таблицы вида остаются nil

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

Я пытаюсь выяснить, что может быть здесь отсутствую, но до сих пор, я гавань» t удалось исправить проблему, и я начинаю терять надежду. Любая помощь будет оценена по достоинству.

ОБНОВЛЕНИЕ: Чтобы было ясно, на этом снимке проблема осталась.

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

Кажется, что клетки получают создан, но его метки нет.

+0

Я не вижу, где вы звоните 'configureForTodoItem:'. Более того, я понятия не имею, что вы пытаетесь сделать с двумя строками между созданием 'cell' и return' cell'. – nhgrif

+0

configureForTodoItem: вызывается из контроллера вида (в блоке configureCell). После создания ячейки я просматриваю запись в соответствующей строке и вызываю метод configure, чтобы установить метки ячеек для свойств этой записи. –

+0

И где называется 'setupTableView'? Я не понимаю ни малейшего, что пытается сделать этот код. Что вы в целом пытаетесь достичь? – nhgrif

ответ

1

Если все, что вы хотите сделать, это отдельный делегат datasource 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 «с и не должны осуществлять протоколов в ваш контроллер просмотра.

Внутри контроллера вида вы создаете свойство datasource с использованием протокола выше.

#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 теперь обрабатывает представление данных в виде таблицы. Контроллер просмотра просто используется для настройки ячейки. Это позволяет вам использовать пользовательские UITableViewCells на каждом ViewController, если вы хотите, и не нужно каждый раз использовать источники данных.

ОБНОВЛЕНО

При условии лучшего примера, полный шаблон проекта.

+0

Johnathon, спасибо за подробный ответ, это отличный пример. Что меня беспокоит по поводу моего вопроса, так это то, что мои ячейки представления таблицы не создаются, хотя я думаю, что делаю это правильно. –

+0

Один вопрос: не так ли плохо, что класс TDSTableViewDataSource содержит сильные ссылка на TDSViewController и наоборот? –

+0

Я не уверен честно. Ссылка на VC может быть слабой, я полагаю, и просто сильно ссылаюсь на нее из VC –

0

После нескольких часов копания, я сумел решить эту проблему (на данный момент), путем изменения точек моей пользовательских ячейки сильных свойств, и инициализирует их в методе инициализации ячейки:

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

Это очень странно, так как я думал, что, создавая свои взгляды в раскадровке, это должно быть автоматически позабочено, и мне никогда не приходилось делать это вручную раньше.

+0

Да, что-то еще не так. Вы не должны настраивать представления UITableViewCell как сильные. Эта ячейка уже сильно привязана к ней. Вы добавляете эти выходные в заголовок вправо? –

+0

Да, они находятся в заголовке, и они подключены к соответствующим объектам раскадровки, но по какой-то причине они не инициализируются. –

+0

Установили ли вы уникальные идентификаторы в раскадровке? Установка идентификаторов в раскадровке, а затем вызов [cell dequeCellWithIdentifier] внутри вашего cellForRowAtIndexPath, он должен инициализировать для вас –

1

В ViewDidLoad зарегистрировать перо, это исправить эту проблему :)

-(void)viewDidLoad 
    { 
     [self.leftTableView registerNib:[UINib nibWithNibName:NIB_FILE bundle:nil] forCellReuseIdentifier:CELL_IDENTIFIER]; 
    } 
Смежные вопросы