UITableViewCell更改UITableView的数据源

时间:2014-01-28 16:42:55

标签: ios iphone objective-c uitableview

这对我来说真的很有用,因为我一直在努力解决这个问题。每次我尝试创建自定义UITableViewCell并在UITableView中使用它时,事情就会变得混乱。我相信这是因为我用来填充单元格的函数,在这个例子中它的名字是fillPlayerCellWithPlayer:。

我有一个玩家联系人的NSArray作为我的UITableView的数据源。我的想法是用每个PlayerContact属性填充单元格的内容,如UILabels和UIImageViews等。通常的做法是在cellForRowAtIndexPath中填充这些属性,如:tablecell.playerNameLabel.text = player.playerName,依此类推。但为了方便起见,我将其实施如下,我将在后面说明:

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *cellIdentifier = @"PlayerCellID";
    AddPlayerObjectCell *tablecell = (AddPlayerObjectCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    NSArray * chosenPlayerArray = [self generatePlayersArrayForCategoryRow:selectedCategoryIndexRow];
    NSMutableDictionary * dict = (NSMutableDictionary *)[chosenPlayerArray objectAtIndex:indexPath.row];
    PlayerContact * player = (PlayerContact *)[dict objectForKey:@"sgfPlayer"];
    [tablecell fillPlayerCellWithPlayer:player];
    return tablecell;}

要解释为什么我不使用常规练习方法,首先让我分享fillPlayerCellWithPlayer函数:

- (void) fillPlayerCellWithPlayer : (PlayerContact *) player {
    [self createGestureRegocnizer];
    myPlayer = player;  //this sets the player as the private variable of AddPlayerObjectCell class
    cellItemLabel.text = myPlayer.playerName;
    cellItemSubLabel.text = myPlayer.playerTeam;
    UIImage * img = [UIImage imageNamed:@"messi.JPG"];
    cellItemImageView.image = img; }

- (void) createGestureRegocnizer{
    UITapGestureRecognizer *gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapFrom)];
    gesture.delegate = self;
    [self addGestureRecognizer:gesture];}

- (void) handleTapFrom{
    NSString * imageName = @"unselected_user_icon.png";
    NSString * imageNameSelected = @"selected_user_icon.png";
    if(playerSelected){
        playerSelected = NO;
        myPlayer.playerSelected = playerSelected;
        [cellItemSelectionImageView setImage:[UIImage imageNamed:imageName]];}
    else{
        playerSelected = YES;
        myPlayer.playerSelected = playerSelected;
        [cellItemSelectionImageView setImage:[UIImage imageNamed:imageNameSelected]];}}

正如您所看到的,当用户触摸单元格时,handleTapFrom会触发,我可以更改myPlayer的playerSelected属性,以便稍后我可以使用此信息过滤我的主阵列以供选定的玩家使用

我的一个问题是,每当我在玩家的桌面视图中滑动手指时,他们选择的选中标记就会变得像疯了一样。我想这是由于我以错误的方式使用可重用单元逻辑引起的。如果你们能给我一个正确的方法,我会非常高兴。

我的第二个问题对我来说更重要,因为如果你们说的是真的,我想在整个app设计中将它作为一般逻辑使用。假设我将名为playersArray的NSArray传递给tableview作为数据源。并且单元类更改了与其indexPath对应的playersArray对象。在我的控制器类和可以访问playersArray的类中,观察到了这种变化。这对我来说是个好消息,因为我不需要复制数组并相应地更改其内容。你认为这对UITableViewCell更改其UITableView的DataSource内容是一个好习惯吗?或者是UITableViewCell唯一可以根据需要显示单元格的工作?我应该以其他方式实现吗?像委托或其他什么,如果我想更新数据源?

非常感谢您提前。无论如何,如果你们需要我,我可以更加清楚。

Aytunçİşseven

1 个答案:

答案 0 :(得分:2)

通常,您应该避免Cell正在持有数据模型并操纵它们。你也应该避免创建&多次添加此手势识别器(如果您调用fillPlayerCellWithPlayer将会发生这种情况:并且重复使用该单元格)。这将增加敲击识别器的数量,并且每个将触发敲击。相反,你可以覆盖

- (void)setSelected:(BOOL)selected animated:(BOOL)animated
在UITableViewCell上

并在那里处理您的选择。每次更改UITableViewCell的选择状态时都会触发此操作。您应该只更改单元格的视觉外观,因为单元格不应该保持播放器对象。

要处理选择播放器,只需实现UITableViewDelegate方法(在控制器上)

- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath

并在那里处理数据模型的操作。

原因是:

UITableViewCell是一个视图,遵循模型 - 视图 - 控制器模式(Appkit所基于的),视图应该只代表模型而不管理它。控制器(实现UITableViewDelegate - 例如UIViewController)是这两者之间的连接器,应该是管理模型信息而不是你建议的视图的连接器。