这对我来说真的很有用,因为我已经为这个问题苦苦挣扎了一段时间。每次我尝试创建自定义 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/