在UITableViewCell中使用复选框-复选框和单元格行为必须不同时 [英] Using Checkboxes in UITableViewCell - when the checkbox and the cell behaviour must be different

查看:70
本文介绍了在UITableViewCell中使用复选框-复选框和单元格行为必须不同时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在遵循此问题中的步骤:
如何在使用UITableViewCell缓存的同时向左侧的UITableView添加复选框?



I不想使用一个简单的复选框来检查是否点击了行,我需要一个仅在点击该复选框时才更改的复选框,因为单元格本身已经加载了所选内容的详细视图项目。




  • 我如何向右移动单元格,以便能够正确查看选中的按钮? (解决了这一问题:在情节提要中,选择单元格,转到属性检查器,然后更改标识的宽度)


  • 标记应使用什么,因为 indexPath.row 不起作用?如果我选择第一个项目,它将检查第8个(在选定的答案中解决了这个问题)




更新:即使我选择了正确的答案,也只能部分解决我的问题。重新加载视图时,选中的项目将移至该部分的末尾,而不是保持以前的顺序。有人知道为什么吗?





这是cellForRowAtIndexPath的更新代码:

  -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell * cell = [tableView2 dequeueReusableCellWithIdentifier:@ Cell2];
UIButton * checkBox;
if(cell.tag == 0){
checkBox = [[UIButton alloc] initWithFrame:CGRectMake(5,10,20,20)];
UIImage * normalImage = [UIImage imageNamed:@ unchecked.png];
UIImage * selectedImage = [UIImage imageNamed:@ checked.png];
[checkBox setImage:NormalImage forState:UIControlStateNormal];
[checkBox setImage:selectedImage forState:UIControlStateSelected];
[checkBox addTarget:self操作:@selector(makeWatched :) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:checkBox];
cell.tag = 1;
}

for(cell.contentView.subviews中的id obj){
if([[obj isKindOfClass:[UIButton class]]){
checkBox = obj;
checkBox.tag = indexPath.row;
休息时间;
}
}


Episodi * epi = [self.fetchedResultsController objectAtIndexPath:indexPath];


checkBox.selected =([self.selectedChecks containsObject:[NSNumber numberWithInt:(indexPath.row)]])?是:否;

if([epi.watched isEqualToString:@ 1]){

NSLog(@ Entra);
checkBox.selected =是;

}

cell.textLabel.text = epi.episodeTitle;
个返回单元格;

}



复选框的更新代码操作:

 -(void)makeWatched:(UIButton *)checkButton {
if(checkButton.selected == NO ){

Episodi * epi = [self.fetchedResultsController objectAtIndexPath:[NSIndexPath indexPathForRow:checkButton.tag inSection:sectionNumber]]];
[epi setWatched:@ 1];
checkButton.selected =是;
NSError *错误=无;
if(![managedObjectContext save:& error]){
NSLog(@保存更改失败:%@,错误);
} else {
//更改已保留。
}

[self.selectedChecks addObject:[NSNumber numberWithInt:(checkButton.tag)]]];


[self.tableView2 reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:checkButton.tag inSection:sectionNumber]] withRowAnimation:UITableViewRowAnimationNone];



}否则{

Episodi * epi = [self.fetchedResultsController objectAtIndexPath:[NSIndexPath indexPathForRow:checkButton.tag inSection:sectionNumber]];
[epi setWatched:@ 0];
if([epi.watched isEqualToString:@ 0]){
NSLog(@不再关注);
}
checkButton.selected = NO;
NSError *错误=无;
if(![managedObjectContext save:& error]){
NSLog(@保存更改失败:%@,错误);
} else {
//更改已保留。
}


[self.selectedChecks removeObjectIdenticalTo:[NSNumber numberWithInt:(checkButton.tag)]]];
[self.tableView2 reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:checkButton.tag inSection:sectionNumber]] withRowAnimation:UITableViewRowAnimationNone];
}
}


解决方案

一个您做错的事情是在一个单元格中添加多个复选框。如果单元格不是nil,则输入 else子句-该单元格已经有一个带有其标签的复选框。然后,您可以使用自己的标签向该单元格添加另一个复选框。



您应该将代码重构为仅在单元格为nil时添加任何子视图。与内容有关的任何事情,包括复选框的标记,都应在if子句之外完成。



编辑后:



这是一种方法。我将复选框的创建包装在if语句中,以便仅将一个复选框添加到单元格中(新创建的单元格的默认标记值为0)。我有一个数组selectedSelects,该数组保存所有复选框的行(记住要在viewDidLoad中创建该数组)。

  -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@ Cell];
UIButton * checkBox;
if(cell.tag == 0){
checkBox = [[UIButton alloc] initWithFrame:CGRectMake(-5,10,20,20)];
UIImage * normalImage = [UIImage imageNamed:@ Uncheck.png];
UIImage * selectedImage = [UIImage imageNamed:@ Check.png];
[checkBox setImage:NormalImage forState:UIControlStateNormal];
[checkBox setImage:selectedImage forState:UIControlStateSelected];
[checkBox addTarget:self操作:@selector(makeWatched :) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:checkBox];
cell.tag = 1;
}

for(cell.contentView.subviews中的id obj){
if([[obj isKindOfClass:[UIButton class]]){
checkBox = obj;
checkBox.tag = indexPath.row;
休息时间;
}
}
checkBox.selected =([[self.selectedChecks containsObject:@(indexPath.row)]])?是:否;
cell.textLabel.text = self.theData [indexPath.row];
个返回单元格;
}


-(void)makeWatched:(UIButton *)checkButton {
if(checkButton.selected == NO){
[self。 selectedChecks addObject:@(checkButton.tag)];
[self.tableView reloadRowsAtIndexPaths:@ [[[NSIndexPath indexPathForRow:checkButton.tag inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
} else {
[self.selectedChecks removeObjectIdenticalTo:@(checkButton.tag)]];
[self.tableView reloadRowsAtIndexPaths:@ [[[NSIndexPath indexPathForRow:checkButton.tag inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
}
}

这应该可行,但我认为创建起来更容易为您的单元格创建一个自定义类,然后在情节提要中添加按钮,并在您的自定义单元格.h文件中为该按钮添加一个IBOutlet。


I have been following the steps in this question: How to add a checkbox to a UITableView on the left, while using UITableViewCell caching?

I don't want a simple check box that gets checked if a row is tapped, I need a check box that changes only when the checkbox is tapped, since the cell itself already loads a detailed view for the selected item.

  • How can I "move" the cell to the right, to be able to see the checked button properly? (solved this one: in Storyboard, select the cell, go to Attributes Inspector, and change the width of the identation)

  • What should I use for the tags, since indexPath.row does not work? If I select the first item, it checks the 8th(solved this one in the selected answer)

UPDATE: Even though I selected an answer as correct, it only solved my problem partially. The checked items are moved to the end of the section when the view is reloaded, instead of keeping the same order they had previously. Anyone knows why?

Here is the updated code for cellForRowAtIndexPath:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView2 dequeueReusableCellWithIdentifier:@"Cell2"];
UIButton *checkBox;
if (cell.tag == 0) {
    checkBox = [[UIButton alloc]initWithFrame:CGRectMake(5, 10, 20, 20)];
    UIImage *normalImage = [UIImage imageNamed: @"unchecked.png"];
    UIImage *selectedImage = [UIImage imageNamed: @"checked.png"];
    [checkBox setImage:normalImage forState:UIControlStateNormal];
    [checkBox setImage:selectedImage forState:UIControlStateSelected];
    [checkBox addTarget:self action:@selector(makeWatched:) forControlEvents:UIControlEventTouchUpInside];
    [cell.contentView addSubview:checkBox];
    cell.tag = 1;
}

for (id obj in cell.contentView.subviews) {
    if ([obj isKindOfClass:[UIButton class]]) {
        checkBox = obj;
        checkBox.tag = indexPath.row;
        break;
    }
}


Episodi *epi = [self.fetchedResultsController objectAtIndexPath:indexPath];


 checkBox.selected = ([self.selectedChecks containsObject:[NSNumber numberWithInt:  (indexPath.row)]])? YES : NO;

if ([epi.watched isEqualToString:@"1"]) {

    NSLog(@"Entra");
    checkBox.selected = YES;

}

cell.textLabel.text = epi.episodeTitle;
return cell;

}

Updated code for the checkbox action:

-(void)makeWatched:(UIButton *) checkButton {
    if (checkButton.selected == NO) {

       Episodi *epi = [self.fetchedResultsController objectAtIndexPath:[NSIndexPath indexPathForRow:checkButton.tag inSection:sectionNumber]];
       [epi setWatched:@"1"];
       checkButton.selected=YES;
       NSError *error = nil;
       if (![managedObjectContext save:&error]) {
           NSLog(@"Saving changes failed: %@", error);
       } else {
        // The changes have been persisted.
    }

    [self.selectedChecks addObject:[NSNumber numberWithInt:(checkButton.tag)]];


    [self.tableView2 reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:checkButton.tag inSection:sectionNumber]] withRowAnimation:UITableViewRowAnimationNone];



}else{

    Episodi *epi = [self.fetchedResultsController objectAtIndexPath:[NSIndexPath indexPathForRow:checkButton.tag inSection:sectionNumber]];
    [epi setWatched:@"0"];
    if ([epi.watched isEqualToString:@"0"]){
       NSLog(@"Not Watched anymore");
    }
    checkButton.selected=NO;
    NSError *error = nil;
    if (![managedObjectContext save:&error]) {
        NSLog(@"Saving changes failed: %@", error);
    } else {
        // The changes have been persisted.
    }


    [self.selectedChecks removeObjectIdenticalTo:[NSNumber numberWithInt:(checkButton.tag)]];
    [self.tableView2 reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:checkButton.tag inSection:sectionNumber]] withRowAnimation:UITableViewRowAnimationNone];
  }
 }

解决方案

One thing you're doing wrong is adding more than one check box in a cell. You enter the "else" clause if the cell is not nil -- that cell already has a checkbox with its tag. You then add another checkbox to that cell with its own tag.

You should refactor your code to only do the addition of any subviews when the cell is nil. Anything having to do with the content, including the checkbox's tags should be done outside of the if clause.

After Edit:

Here is one way to do it. I wrap the creation of the checkbox in an if statement so that only one checkbox is ever added to a cell (the newly created cell will have the default tag value of 0). I have an array, selectedChecks, that hold the row of all the checked boxes (remember to create that array in viewDidLoad).

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
    UIButton *checkBox;
    if (cell.tag == 0) {
        checkBox = [[UIButton alloc]initWithFrame:CGRectMake(-5, 10, 20, 20)];
        UIImage *normalImage = [UIImage imageNamed: @"Uncheck.png"];
        UIImage *selectedImage = [UIImage imageNamed: @"Check.png"];
        [checkBox setImage:normalImage forState:UIControlStateNormal];
        [checkBox setImage:selectedImage forState:UIControlStateSelected];
        [checkBox addTarget:self action:@selector(makeWatched:) forControlEvents:UIControlEventTouchUpInside];
        [cell.contentView addSubview:checkBox];
        cell.tag = 1;
    }

    for (id obj in cell.contentView.subviews) {
        if ([obj isKindOfClass:[UIButton class]]) {
            checkBox = obj;
            checkBox.tag = indexPath.row;
            break;
        }
    }
    checkBox.selected = ([self.selectedChecks containsObject:@(indexPath.row)])? YES : NO;
    cell.textLabel.text =  self.theData[indexPath.row];       
    return cell;
}


-(void)makeWatched:(UIButton *) checkButton {
    if (checkButton.selected == NO) {
        [self.selectedChecks addObject:@(checkButton.tag)];
        [self.tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:checkButton.tag inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
    }else{
        [self.selectedChecks removeObjectIdenticalTo:@(checkButton.tag)];
        [self.tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:checkButton.tag inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
    }
}

This should work, but I think it's easier to create a custom class for your cell and add the button in the storyboard, and have an IBOutlet to that button in your custom cell .h file.

这篇关于在UITableViewCell中使用复选框-复选框和单元格行为必须不同时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆