21

使用此代码,我可以检查表中的多行。

但我想要的是一次只检查一行。这是我的代码:

- (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;
    }
}

如果用户选择不同的行,那么我希望旧行简单地自动取消选中。不知道该怎么做。

4

18 回答 18

86

目标-C:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath   *)indexPath
{
     [tableView cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryCheckmark;
}

-(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath 
{
    [tableView cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryNone;
}

迅速:

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
}
于 2013-08-01T18:40:45.003 回答
27

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

int selectedIndex;

在你的 cellForRowAtIndexPath

if(indexPath.row == selectedIndex)
{
   cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
   cell.accessoryType = UITableViewCellAccessoryNone;
}

在你的 didSelectRowAtIndex

selectedIndex = indexPath.row;
[tableView reloadData];
于 2013-03-15T07:18:37.010 回答
26

最好的方法是在 中设置附件类型cellForRowAtIndexPath

用于didSelectRowAtIndexPath仅记录选择哪个路径然后调用reloadData.

于 2012-04-17T14:22:43.603 回答
23

您不需要(也不应该)在每次选择后重新加载表格。

Apple 有关于如何管理选择列表的良好文档。示例见清单 6-3。

这与其他一些答案或多或少相同,但我想我会添加更多细节。

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

您需要确保还设置/取消设置 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
    }
}
于 2015-12-10T04:20:51.163 回答
8

您不需要重新加载 tableView。

请参阅以下代码:

为你的类声明一个 NSIndexPathlastSelectedIndexPath变量

- (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;
}
于 2013-07-09T04:48:46.147 回答
5

对于 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
}
于 2017-05-24T08:54:59.050 回答
4

我认为https://stackoverflow.com/a/5960016/928599会帮助你。
我使用了它,它也适用于 deselectRowAtIndexPath!

于 2012-06-07T09:26:12.153 回答
4

最简单的方法是保存选定的 IndexPath 并将其签入cellForRowAtIndexPath

  1. 初始化选定的索引路径:

    selectedIndexPath = [[NSIndexPath alloc] init];
    
  2. cellForRowAtIndexPath

    if([selectedIndexPath isEqual:indexPath]){
        [checkMark setHidden:NO];
    } else {
        [checkMark setHidden:YES];
    }
    
  3. didSelectRowAtIndexPath

    selectedIndexPath = indexPath;
    [tableView reloadData];
    

它应该可以工作试试这个 Njoy :)

于 2013-06-12T11:56:10.283 回答
1

试试这个:

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
    }
}
于 2015-05-15T02:32:23.590 回答
1

在 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)
}
于 2016-03-24T12:37:37.837 回答
0

斯威夫特 iOS

 var checkedIndexPath : NSIndexPath?

// table row which row was selected
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath!) {
    tableView.deselectRowAtIndexPath(indexPath, animated: true)
    
    println("Section #\(indexPath.section)! You selected cell #\(indexPath.row)!")
    
    if (self.checkedIndexPath != nil) {
        var cell = tableView.cellForRowAtIndexPath(self.checkedIndexPath!)
        cell?.accessoryType = .None
    }
    
    var cell = tableView.cellForRowAtIndexPath(indexPath)
    cell?.accessoryType = .Checkmark
    
    self.checkedIndexPath = indexPath
    
}// end tableView
于 2015-02-24T13:52:25.047 回答
0

在 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

}
于 2016-02-17T19:57:18.850 回答
0

我的方法是在选择过程中取消选择其他单元格:

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
}
于 2016-12-20T09:13:32.633 回答
0

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

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
    }
}
于 2017-06-30T03:24:13.743 回答
0

测试并解决了试试这个它工作得很好

将此添加为全局变量

var selectedIndexPath = NSIndexPath(row: 0, section: 0)

在 didselect 方法中添加这个

        // old one check off
        if indexPath != selectedIndexPath as IndexPath {
            let oldCell = categorytable.cellForRow(at: selectedIndexPath as IndexPath)
            if oldCell?.accessoryView != nil {
                oldCell?.accessoryView = nil
            }
            else {
                let imageName = "checkmark"
                let image: UIImageView = UIImageView(image: UIImage(named: imageName))
                cell.accessoryView = image
            }
        }
        // the new one on

        if  cell.accessoryView == nil {
            let imageName = "checkmark"
            let image: UIImageView = UIImageView(image: UIImage(named: imageName))
            cell.accessoryView = image
        }
        else {
            cell.accessoryView = nil
        }
于 2017-08-17T07:58:53.550 回答
0

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

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)

也适用于多项选择。

于 2019-10-18T13:23:48.930 回答
0

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
    }
}
于 2021-01-03T20:22:30.757 回答
0

存储选定的索引路径,在 中更新它didSelectRowAt:,然后从那里调用reloadRows(at:以仅重新加载旧的和新的检查行(而不是整个表视图):

var selectedIndexPath: IndexPath?

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    let previous = selectedIndexPath
    selectedIndexPath = indexPath
    
    let allowDeselection = true // optional behavior
    if allowDeselection && previous == selectedIndexPath {
        selectedIndexPath = nil
    }
    
    tableView.reloadRows(at: [previous, selectedIndexPath].compactMap({ $0 }), with: .automatic)
    tableView.deselectRow(at: indexPath, animated: true)
}

处理复选标记附件视图的设置cellForRowAt indexPath:。这将考虑到单元重用,并且还会由您对 的上述调用触发reloadRows(at:,避免重复设置单元附件的代码:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "IDENTIFIER", for: indexPath)
    
    cell.accessoryType = (indexPath == selectedIndexPath) ? .checkmark : .none
    
    // ...
    
    return cell
}
于 2021-10-04T20:46:18.453 回答