Ios UITableView一次只选中一行

Ios UITableView一次只选中一行,ios,xcode,ios4,ios5,xcode4,Ios,Xcode,Ios4,Ios5,Xcode4,你会认为这很容易。使用这段代码,我可以检查表中的多行,但我希望一次只检查一行。如果用户选择了不同的行,那么我希望旧行自动取消选中。我不知道怎么做。这是我的密码: - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView deselectRowAtIndexPath:indexPath animated:YES]; UITableViewCe

你会认为这很容易。使用这段代码,我可以检查表中的多行,但我希望一次只检查一行。如果用户选择了不同的行,那么我希望旧行自动取消选中。我不知道怎么做。这是我的密码:

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

[tableView deselectRowAtIndexPath:indexPath animated:YES];


UITableViewCell *theCell = [tableView cellForRowAtIndexPath:indexPath];

if (theCell.accessoryType == UITableViewCellAccessoryNone) {
    theCell.accessoryType = UITableViewCellAccessoryCheckmark;
    }

    else if (theCell.accessoryType == UITableViewCellAccessoryCheckmark) {
    theCell.accessoryType = UITableViewCellAccessoryNone;
    }
}

谢谢你的帮助

最好的方法是在CellForRowatineXpath中设置附件类型,并使用DidSelectRowatineXpath仅记录应选择的路径,然后调用重新加载数据。

我认为这会对您有所帮助。

我使用了它,它也可以与DestrowAtIndexPath一起使用

您可以创建一个新变量来跟踪在didSelectRowAtIndex上选择的索引

int selectedIndex;
在你的牢房里

if(indexPath.row == selectedIndex)
{
   cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
   cell.accessoryType = UITableViewCellAccessoryNone;
}
if([selectedIndexPath isEqual:indexPath]){
    [checkMark setHidden:NO];
} else {
    [checkMark setHidden:YES];
}
selectedIndexPath = indexPath;
[tableView reloadData];
在你的DidSelectRowatinex中

selectedIndex = indexPath.row;
[tableView reloadData];

最简单的方法是保存选定的IndexPath并在CellForRowatineXpath中检查它

随函附上代码:

步骤1:初始化selectedIndexPath selectedIndexPath=[[NSIndexPath alloc]init]

步骤2:在cellForRowAtIndexPath中

if(indexPath.row == selectedIndex)
{
   cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
   cell.accessoryType = UITableViewCellAccessoryNone;
}
if([selectedIndexPath isEqual:indexPath]){
    [checkMark setHidden:NO];
} else {
    [checkMark setHidden:YES];
}
selectedIndexPath = indexPath;
[tableView reloadData];
步骤3:在didSelectRowAtIndexPath中

if(indexPath.row == selectedIndex)
{
   cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
   cell.accessoryType = UITableViewCellAccessoryNone;
}
if([selectedIndexPath isEqual:indexPath]){
    [checkMark setHidden:NO];
} else {
    [checkMark setHidden:YES];
}
selectedIndexPath = indexPath;
[tableView reloadData];

应该可以试试这个Njoy:)

您不需要重新加载tableView

请参阅以下代码:

为类声明nsindepath
lastSelectedIndexPath
变量

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

    if(lastSelectedIndexPath) {

        UITableViewCell *lastCell = [tableView cellForRowAtIndexPath:lastSelectedIndexPath];
        [lastCell setAccessoryView:nil];
    }

    UITableViewCell *currentCell = [tableView cellForRowAtIndexPath:currentIndexPath];
    [currentCell setAccessoryView:UITableViewCellAccessoryCheckmark];

    lastSelectedIndexPath = indexPath;
}
Swift
版本为:

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    tableView.cellForRowAtIndexPath(indexPath)?.accessoryType = .Checkmark
}

override func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
    tableView.cellForRowAtIndexPath(indexPath)?.accessoryType = .None
}
Swift 3
更新

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    tableView.cellForRow(at: indexPath)?.accessoryType = .checkmark
}

override func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
    tableView.cellForRow(at: indexPath)?.accessoryType = .none
}
Swift 5更新

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    tableView.cellForRow(at: indexPath)?.accessoryType = .checkmark
}

func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
    tableView.cellForRow(at: indexPath)?.accessoryType = .none
}
试试这个:

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    if indexPath.section == 1 {
        // un-select the older row
        if let selected = self.LastSelected {
            tableView.cellForRowAtIndexPath(selected)?.accessoryType = .None
        }

        // select the new row
        tableView.cellForRowAtIndexPath(indexPath)?.accessoryType = UITableViewCellAccessoryType.Checkmark
        self.LastSelected = indexPath
    }
}
您不需要(也不应该)在每次选择后重新加载表

苹果在如何管理选择列表方面有很好的经验。有关示例,请参见清单6-3

这与其他一些答案大致相同,但我想我应该补充一点细节

您要做的是将当前选定的IndexPath保存到一个变量中,并在DidSelectRowatineXpath中使用该变量删除旧的复选标记。这也是添加新复选标记的地方

您需要确保还设置/取消设置cellForRowAtIndexPath中的复选标记,否则,如果列表较大且重复使用单元格,则看起来会选择多行。这是其他一些答案的问题

参见下面的swift 2.0示例:

// for saving currently seletcted index path
var selectedIndexPath: NSIndexPath? = NSIndexPath(forRow: 0, inSection: 0)  // you wouldn't normally initialize it here, this is just so this code snip works
// likely you would set this during cellForRowAtIndexPath when you dequeue the cell that matches a saved user selection or the default

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    // this gets rid of the grey row selection.  You can add the delegate didDeselectRowAtIndexPath if you want something to happen on deselection
    tableView.deselectRowAtIndexPath(indexPath, animated: true) // animated to true makes the grey fade out, set to false for it to immediately go away

    // if they are selecting the same row again, there is nothing to do, just keep it checked
    if indexPath == selectedIndexPath {
        return
    }

    // toggle old one off and the new one on
    let newCell = tableView.cellForRowAtIndexPath(indexPath)
    if newCell?.accessoryType == UITableViewCellAccessoryType.None {
        newCell?.accessoryType = UITableViewCellAccessoryType.Checkmark
    }
    let oldCell = tableView.cellForRowAtIndexPath(selectedIndexPath!)
    if oldCell?.accessoryType == UITableViewCellAccessoryType.Checkmark {
        oldCell?.accessoryType = UITableViewCellAccessoryType.None
    }

    selectedIndexPath = indexPath  // save the selected index path

    // do whatever else you need to do upon a new selection
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
    // if this is the currently selected indexPath, set the checkmark, otherwise remove it
    if indexPath == selectedIndexPath {
        cell.accessoryType = UITableViewCellAccessoryType.Checkmark
    } else {
        cell.accessoryType = UITableViewCellAccessoryType.None
    }
}

在Swift 2.0中,我使用了以下内容:

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

    if((lastSelectedIndexPath) != nil) {
        let lastCell = tableView.cellForRowAtIndexPath(lastSelectedIndexPath)
        lastCell?.accessoryType = UITableViewCellAccessoryType.None
    }

    let currentCell = tableView.cellForRowAtIndexPath(indexPath)
    currentCell?.accessoryType = UITableViewCellAccessoryType.Checkmark

    lastSelectedIndexPath = indexPath

}

在Swift中,以下操作非常有效:

lastSelectedIndexPath = NSIndexPath(forRow: 1, inSection: 0)//Row will be the previous selected row


    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
    let cell:LabelsSelectionCell = tableView.dequeueReusableCellWithIdentifier("LabelsSelectionCell", forIndexPath: indexPath) as! LabelsSelectionCell
    cell.setCellLael(labelOptionsArray[indexPath.row])
    if lastSelectedIndexPath == indexPath
    {
        cell.setCellCheckedStatus(true)
    }
    return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
    if let _ = lastSelectedIndexPath
    {
        let lastCell:LabelsSelectionCell = tableView.cellForRowAtIndexPath(lastSelectedIndexPath!) as! LabelsSelectionCell
        lastCell.setCellCheckedStatus(false)
    }
    let currentCell:LabelsSelectionCell = tableView.cellForRowAtIndexPath(indexPath) as! LabelsSelectionCell
    currentCell.setCellCheckedStatus(true)

    lastSelectedIndexPath = indexPath

    tableView.deselectRowAtIndexPath(indexPath, animated: true)
}

我的方法是在选择期间取消选择其他单元格:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = ....

    if condition {
        cell.accessoryType = .checkmark
        tableView.selectRow(at: indexPath, animated: false, scrollPosition: UITableViewScrollPosition.bottom)
    } else {
        cell.accessoryType = .none
    }

    return cell
}

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    for row in 0...tableView.numberOfRows(inSection: 0) {
        if row == indexPath.row {continue}
        tableView.deselectRow(at: IndexPath(row: row, section: 0), animated: true)
    }

    if let cell = tableView.cellForRow(at: indexPath) {
        cell.accessoryType = .checkmark
    }
}

func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
    let cell = tableView.cellForRow(at: indexPath)
    cell?.accessoryType = .none
}

对于Swift 3,以下内容适用于我:

override func viewDidLoad() {
    super.viewDidLoad()

    // allow cells to be selected
    tableView.allowsSelection = true

    // ensure that deselect is called on all other cells when a cell is selected
    tableView.allowsMultipleSelection = false
}

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    tableVIew.cellForRow(at: indexPath as IndexPath)?.accessoryType = .checkmark
}

func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
    tableVIew.cellForRow(at: indexPath as IndexPath)?.accessoryType = .none
}

这是我遇到这个问题时想到的。
从今天起,此代码在最新版本的Swift中实施…
有关更多信息和/或扩展文件,请查看此代码段的

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {       
    if let sip = selectedIndex {
        tableView.deselectRow(at: sip, animated: false)
    }
    selectedIndex = indexPath
}

override func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
    if selectedIndex?.row == indexPath.row {
        selectedIndex = nil
    }
}

经过测试并解决了这个问题,尝试一下,它工作得非常好

将其添加为全局变量

将此添加到didselect方法中


您可以在一行代码的自定义单元格类型中执行此操作

final class CheckableTableViewCell: UITableViewCell {

  override func setSelected(_ selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)

    self.accessoryType = selected ? .checkmark : .none
  }

}
要使此方法正常工作,应选择您的单元格

如果不想看到所选单元格的突出显示,只需在情节提要或代码中将单元格的selectionStyle设置为.none即可

如果您要调用

tableView.deselectRow(at: indexPath, animated: true)

也适用于多种选择。

jeffjv响应的Swift 5版本

// for saving currently selected index path
var selectedIndexPath: NSIndexPath? = NSIndexPath(forRow: 0, inSection: 0)  // you wouldn't normally initialize it here, this is just so this code snip works
// likely you would set this during cellForRowAtIndexPath when you dequeue the cell that matches a saved user selection or the default

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: IndexPath) {
    // this gets rid of the grey row selection.  You can add the delegate didDeselectRowAtIndexPath if you want something to happen on deselection
    tableView.deselectRow(at: indexPath, animated: true) // animated to true makes the grey fade out, set to false for it to immediately go away

    // if they are selecting the same row again, there is nothing to do, just keep it checked
    if indexPath == selectedIndexPath! as IndexPath {
        return
    }

    // toggle old one off and the new one on
    let newCell = tableView.cellForRow(at: indexPath)
    if newCell?.accessoryType == UITableViewCell.AccessoryType.None {
        newCell?.accessoryType = UITableViewCell.AccessoryType.Checkmark
    }
    let oldCell = tableView.cellForRow(at: selectedIndexPath! as IndexPath)
    if oldCell?.accessoryType == UITableViewCell.AccessoryType.Checkmark {
        oldCell?.accessoryType = UITableViewCell.AccessoryType.None
    }

    selectedIndexPath = indexPath as NSIndexPath  // save the selected index path

    // do whatever else you need to do upon a new selection
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
    // if this is the currently selected indexPath, set the checkmark, otherwise remove it
     if indexPath == selectedIndexPath! as IndexPath {
        cell.accessoryType = UITableView.CellAccessoryType.Checkmark
    } else {
        cell.accessoryType = UITableView.CellAccessoryType.None
    }
}


对于那些回答正确的问题,您应该通过单击旁边的复选标记来接受正确答案。此解决方案的唯一问题是您将丢失“取消选择行”动画。只需重新加载其他可见单元格。我肯定会先选择“正确”,然后再选择“漂亮”,如果需要的话。:-)再次感谢你!重新加载数据是使事情正常运行的关键。非常感谢你的洞察力。在这种情况下,正确和漂亮是可以实现的。因此,没有必要求助于
reloadData
。您不需要(也不应该)调用reloadData来解决这个问题。请参阅其他一些答案(如我的),以正确处理动画和可重用性。有人知道如何使用nsUserDeafolts保存所选行的状态吗?我一直在寻找一种简单的方法。我找到的所有解决方案都相当复杂,对于我的项目来说,这只会把我的代码弄得乱七八糟。@Borges你能再解释一下你的问题吗?你说的细胞状态到底是什么意思?最好的解决方案!非常感谢。这不考虑可重用性。小心。同意@p0lAris。当细胞被重复使用时。它仍然有复选标记。如果您的表格中的行数少于屏幕上的行数,这是可以的,但一旦它们溢出并在滚动过程中被重新使用(如@p0lAris所说),您的用户将非常困惑。@HardikAmal-很简单,只需在配置单元格以最终设置附件类型时添加条件即可。因此,请确保将
else
放在
if
之后,并设置任意一种方式的值。如果(self.checkedIndexPath!=nil){var cell=tableView.cellforrowtIndexPath(self.checkedIndexPath!)cell?.accessoryType=.None},则当“checkedIndexPath”不在tableView的可访问单元格中时,它将崩溃如果单元格不在可见单元格中,则该单元格为零。上次选择的单元格是否初始化并管理?as lastSelectedIndexPath永远不能为nilvar lastSelectedIndexPath:NSIndexPath?=nsindepath(forRow:0,第0节)
var lastSelectedIndexPath:nsindepath
在开始时是nil,但在之后,我用if检查if是否为nil,在函数的末尾我做了:
lastSelectedIndexPath=indexPath
请声明为NSINTEGER而不是Int。简单地说,这段代码就足够了,谢谢。约翰·保罗·马诺扎简直是个了不起的人!此解决方案还适用于不断选择单元格中的任何内容。伟大的你救了我一天!:)你救了我一天这个答案很神奇,但它假设
selectedIndexPath
已初始化,不是吗?我的意思是,如果初始化表视图时没有默认值,
didSelectRowAtIndexPath
应该尝试展开
selectedIndexPath
并设置value@matteodv,在我的代码剪贴中,我在第三行有一条注释,上面写着
//很可能