UITableView一次只能选中一行

Jup*_*869 18 xcode ios4 ios xcode4 ios5

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

- (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;
    }
}
Run Code Online (Sandbox Code Playgroud)

感谢您提供的任何帮助!

小智 83

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

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

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
}
Run Code Online (Sandbox Code Playgroud)

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
}
Run Code Online (Sandbox Code Playgroud)

  • 这并不重视可重用性.小心. (2认同)

Phi*_*lls 24

最好的方法是在cellForRowAtIndexPath中设置附件类型,并使用didSelectRowAtIndexPath仅记录选择的路径,然后调用reloadData.

  • 此解决方案的唯一问题是您将丢失取消选择行动画。只需重新加载其他可见单元格即可。 (2认同)
  • 在这种情况下,正确且漂亮是可以实现的。所以没有必要诉诸“reloadData”。 (2认同)
  • 您不(也不应该)调用 reloadData 来解决此问题。请参阅其他一些答案(例如我的答案)以正确处理动画和可重用性。 (2认同)

Joh*_*oza 23

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

int selectedIndex;
Run Code Online (Sandbox Code Playgroud)

在你的cellForRowAtIndexPath中

if(indexPath.row == selectedIndex)
{
   cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
   cell.accessoryType = UITableViewCellAccessoryNone;
}
Run Code Online (Sandbox Code Playgroud)

并在你的didSelectRowAtIndex中

selectedIndex = indexPath.row;
[tableView reloadData];
Run Code Online (Sandbox Code Playgroud)


jef*_*fjv 18

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

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
    }
}
Run Code Online (Sandbox Code Playgroud)


Bur*_*ala 8

您不需要重新加载tableView.

请参阅以下代码:

lastSelectedIndexPath为您的类声明一个NSIndexPath 变量

- (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;
}
Run Code Online (Sandbox Code Playgroud)


小智 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
}
Run Code Online (Sandbox Code Playgroud)