ios - UITableViewCell 改变 UITableView 的数据源

标签 ios iphone objective-c uitableview

这对我来说真的很有用,因为我已经为这个问题苦苦挣扎了一段时间。每次我尝试创建自定义 UITableViewCell 并在 UITableView 中使用它时,事情都会变得困惑。我相信这是因为我用来填充单元格的函数,在这个例子中它的名字是 fillPlayerCellWithPlayer:。

我有一个 PlayerContacts 的 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 属性,以便稍后使用此信息进行过滤选定球员的主要阵容。

我的一个问题是,每当我在玩家的表格 View 中滑动手指时,他们选择的复选标记就会疯狂地改变。我想这是由于我以错误的方式使用可重用单元格逻辑造成的。如果你们能给我建议一个正确的方法,我会很高兴。

我的第二个问题对我来说更重要,因为如果你们说它是真的,我想在我的应用程序设计中将它用作一般逻辑。假设我将一个名为 playersArray 的 NSArray 作为数据源传递给了 tableview。而cell类改变了它的indexPath对应的playersArray对象。在我的 Controller 类和可以访问 playersArray 的类中,可以观察到这种变化。这对我来说是个好消息,因为我不需要复制数组并相应地更改其内容。各位小伙伴认为这是一个UITableViewCell改变其UITableView的DataSource的内容的好做法吗?还是 UITableViewCell 的唯一工作是根据需要显示单元格?我应该以其他方式实现吗?如果我想更新数据源,比如委托(delegate)之类的?

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

Aytunç İşseven

最佳答案

一般来说,您应该避免 Cell 本身持有数据模型并对其进行操作。您还应该避免多次创建和添加此手势识别器(因为如果您调用 fillPlayerCellWithPlayer: 并且单元格被重用,就会发生这种情况)。这将增加敲击识别器的数量,并且每个识别器都会触发敲击。相反,您可以覆盖

- (void)setSelected:(BOOL)selected animated:(BOOL)animated

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

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

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

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

原因是:

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

关于ios - UITableViewCell 改变 UITableView 的数据源,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21411599/

相关文章:

iphone - iPhone模拟器视频捕捉软件

objective-c - 以编程方式创建 View 和 subview

c++ - 从 C++ 库创建一个 Swift 共享框架

ios - UICollectionViewCell 呼吸时圆角恢复为方形

iphone - 如何在xcode中创建控件

iphone - 缺少 AVFoundation.framework

iphone - Admob banner integration in Cocos2d 2.0/Admob banner in iphone 游戏

objective-c - 创建结构时的内联 block

ios - 如何从分组的 UITableView 的单元格中删除边框?

ios - 在字符串中查找 8 位数字字符串 - Objective C