为 tableView 单元格投射到正确的对象

Posted

技术标签:

【中文标题】为 tableView 单元格投射到正确的对象【英文标题】:Casting to right object for tableView cells 【发布时间】:2012-09-01 12:49:30 【问题描述】:

我正在使用 tableView 来显示每个带有不同数据的 tam tableView。 当我回到所有 tableView 代表的界面时,我正在用基于前一个视图的数据(带有字段的不同数组)来吸引 *list

if(select = names )...
  list = myData.Names;
if (select = workers)...
  list = myData.Workers;

等等……

在我使用的代表表中:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
    return [list count];

但是当我为表格单元格初始化对象时,我怎样才能为单元格设置正确的对象。现在我使用硬编码:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) 
          cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"MyIdentifier"] autorelease];       
    
    //HARD-CODED
    names *s = [list objectAtIndex:indexPath.row];
    cell.textLabel.text = names.firstName;
    cell.detailTextLabel.text=s.lastName;
    return cell;   

当我将list 设置为workers 时,我怎么知道每次都投射到正确的对象?不写数百万if

例如如果

  if (select = workers)...
          list = myData.Workers;

[list count] 将返回正确的数字,但我想根据列表显示数据,我该如何转换它以便自动声明工人

workers *s = [list objectAtIndex:indexPath.row];

【问题讨论】:

你到底为什么要投? 单元格的对象,在示例中我使用名称 *s,但如果我将列表设置为工人,我需要将其设置为工人 *s 以使用工人字段 无法追踪问题..你能解释清楚..什么是列表,名称.. 你能举例说明工人以外的其他类是什么样的吗?它们是否都共享相同的界面,意思是:它们都具有@property 姓氏、名字等吗? @pmd 我编辑了这个问题,但不,这就是问题所在,名字有:lastName,FirstName... Workers:salary,company... 【参考方案1】:

我想我理解你的问题,所以让我试着解释一下:

这可以使用协议轻松解决,并将单元配置责任交给实际对象。

首先,声明你的类将遵循的协议:

@class MyTableViewCell;

@protocol CellConfiguring

- (void)configureCell:(MyTableViewCell *)cell;

@end

现在创建一些类并确保它们都符合这个协议:

@interface Workers : NSObject <CellConfiguring>

@property (retain, nonatomic) NSString *company;
@property (retain, nonatomic) NSString *salary;

@end

和:

@interface Names : NSObject <CellConfiguring>

@property (retain, nonatomic) NSString *firstName;
@property (retain, nonatomic) NSString *lastName;

@end

等等……

在他们的实现中,他们每个人都会以不同的方式处理单元格的配置:

#import "MyTableViewCell.h"

@implementation Workers

- (void)configureCell:(MyTableViewCell *)cell

    cell.textLabel.text = self.company;
    cell.detailTextLabel.text = self.salary;


@end

和:

#import "MyTableViewCell.h"

@implementation Names

- (void)configureCell:(MyTableViewCell *)cell

    cell.textLabel.text = self.firstName;
    cell.detailTextLabel.text = self.lastName;


@end

请记住,您收到的单元格是您创建的自定义单元格。例如:

@interface MyTableViewCell : UITableViewCell

@property (retain, nonatomic) UILabel *textLabel;
@property (retain, nonatomic) UILabel *detailTextLabel;

@end

现在,在您的委托电话中:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 

    MyTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) 
          cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"MyIdentifier"] autorelease];       
    

    id myObject = [list objectAtIndex:indexPath.row];
    if ([myObject conformsToProtocol:@protocol(CellConfiguring)]
        [myObject configureCell:cell];    
    return cell;   

就是这样。不再有 if-else 语句和强制转换。

提示:每当您开始在类中看到太多 if-else 语句、弄脏您的代码时,请开始考虑责任。对象是否应该负责弄清楚如何配置单元?或者我们可以将该任务委托给另一个对象吗?

【讨论】:

,听起来是正确的解决方案,一件事......我在一个新接口中创建了协议,但是当我在每个类中实现协议时,他们无法识别@987654328 @ 你需要一个具有这样标签的 UITableViewCell 子类。例如 MyTableViewCell,然后只需 #import "MyTableViewCell.h"。我以为你已经有一个自定义的 UITableViewCell。让我更新一下我的问题。 抱歉无法理解...我正在 MyTable 界面中创建表格。我用这个代码创建了一个新协议:@class Mytable; @protocol CellConfig -(void)configCell: (MyTable *) cell,但是当我在每个类上实现它时,我的钢没有textLabel 改用 cell.titleLabel.text【参考方案2】:

在 .h 文件中设置一个标志,如 BOOL 标志。数据会根据flag填充。

最初标志在 ViewDidLoad 中为 TRUE。

现在设置这样的列表:

if()...
listNames = myData.Names;
if ()...
listWorkers = myData.Workers;

在表中代表:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
 if(flag)
 return [listNames count];
 else
 
  return [listWorkers count];
 


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) 
          cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"MyIdentifier"] autorelease];       
    
    if(flag)
    
       names *s = [listNames objectAtIndex:indexPath.row];
       cell.textLabel.text = names.firstName;
       cell.detailTextLabel.text=s.lastName;
       return cell;  
    
    else
   
       names *s = [listWorkers objectAtIndex:indexPath.row];
       cell.textLabel.text = names.firstName; // change for listWorkers
       cell.detailTextLabel.text=s.lastName; // change for listWorkers
       return cell;
    

现在当你想改变的时候

flag = FALSE; //worker data will be filled
[tableView reloadData]

【讨论】:

其实我有超过 20 种类型的对象..所以我想知道如何在没有单元格的所有 if 语句的情况下做到这一点,认为也许有更简单的解决方案,例如一些如何在第一个初始化单元格的 IF 为 20 个不同的对象更换和使用开关盒【参考方案3】:

您也许可以使用以下解决方案...

为每种类型的对象创建一个符合 UITableViewDataSource 的自定义对象。例如 WorkerDataSource、NamesDataSource 等...

根据你要显示的数据,为tableView设置合适的dataSource。我从事的项目中的一个例子......

#define SECTION_HEADER_HEIGHT 20.0f


@interface FSMatchProgrammeDataSource ()

@property (nonatomic, copy) NSArray *matches;
@property (nonatomic, copy) NSArray *groupedMatches;

@end


@implementation FSMatchProgrammeDataSource

@synthesize matches               = _matches;
@synthesize groupedMatches        = _groupedMatches;
@synthesize didSelectMatchHandler = _didSelectMatchHandler;

+ (FSMatchProgrammeDataSource *)dataSourceWithMatches:(NSArray *)matches

    FSMatchProgrammeDataSource *dataSource = [[FSMatchProgrammeDataSource alloc] init];
    if (dataSource)
    
        dataSource.matches = matches;
    
    return dataSource;


#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView

    return _groupedMatches.count;


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

    NSArray *matches = [_groupedMatches objectAtIndex:section];
    return matches.count;


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

    static NSString *CellIdentifier = @"MatchProgrammeCellIdentifier";

    FSMatchProgrammeCell *cell = (FSMatchProgrammeCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (!cell)
    
        cell = [[FSMatchProgrammeCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];        
    

    NSArray *matches = [_groupedMatches objectAtIndex:indexPath.section];
    cell.match = [matches objectAtIndex:indexPath.row];

    DLog(@"%@", cell.match);

    return cell;


#pragma mark - Table view delegate

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section

   // custom view created here ...


- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section

    return SECTION_HEADER_HEIGHT;


- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

    return 44.0f;


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

    if (_didSelectMatchHandler)
    
        NSArray *matches = [_groupedMatches objectAtIndex:indexPath.section];
        FSMatch *match   = [matches objectAtIndex:indexPath.row];

        _didSelectMatchHandler(match);
    


#pragma mark - Properties

- (void)setMatches:(NSArray *)matches

    // matches property set, also an sorted / grouped copy is created for display called groupMatches ...


@end

dataSource 在 tableViewController 中是这样分配的:

- (void)refreshView

    BOOL showInfoLabel = NO;

    switch (_tabBar.selectedSegmentTag)
    
        case TabProgramme:
            _tableView.dataSource = _programmeDataSource;
            _tableView.delegate   = _programmeDataSource;
            break;
        case TabResults: 
            _tableView.dataSource = _resultsDataSource;
            _tableView.delegate   = _resultsDataSource;
            break;
        case TabStandings:
            _tableView.dataSource = _standingsDataSource;
            _tableView.delegate   = _standingsDataSource;
            break;
        default: break;
    

    [self.tableView reloadData];

【讨论】:

以上是关于为 tableView 单元格投射到正确的对象的主要内容,如果未能解决你的问题,请参考以下文章

当我滚动时,TableView 只加载一个单元格的内容

Tableview 单元格将无法正确显示

如何通过stackview将图像添加到tableview单元格

图像未正确加载

更改tableView中偶数单元格的背景颜色

如何使表格视图单元格上的按钮调用正确的 tableView:cellForRowAtIndexPath?