如何取消选择一个选定的UITableView单元格?


212

我正在做一个必须预先选择特定单元格的项目。

我可以使用来预先选择一个单元格-willDisplayCell,但是当用户单击其他任何单元格时都不能取消选择它。

- (void)tableView:(UITableView*)tableView 
        willDisplayCell:(UITableViewCell*)cell
        forRowAtIndexPath:(NSIndexPath*)indexPath
{ 
    AppDelegate_iPad *appDelegte = 
      (AppDelegate_iPad *)[[UIApplication sharedApplication] delegate];

    if ([appDelegte.indexPathDelegate row] == [indexPath row])
    {
        [cell setSelected:YES];    
    } 
}

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

    AppDelegate_iPad *appDelegte = 
      (AppDelegate_iPad *)[[UIApplication sharedApplication] delegate];

    NSIndexPath *indexpath1 = appDelegte.indexPathDelegate;
    appDelegte.indexPathDelegate = indexPath;
    [materialTable deselectRowAtIndexPath:indexpath1 animated:NO];
}

你能帮我吗?


11
这个问题需要有一个公认的答案
Titouan de Bailleul

Answers:


407

使用此代码

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
 {
    //Change the selected background view of the cell.
     [tableView deselectRowAtIndexPath:indexPath animated:YES];
 }

Swift 3.0:

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    //Change the selected background view of the cell.
    tableView.deselectRow(at: indexPath, animated: true)
}

1
有一个didDeselectRowAtIndexPath可以用来取消选择上一个。
huggie 2014年

3
我想认为我不能赞这个帖子,因为它会导致整数溢出:)
Milo 2014年

嗨@ram,您需要选择一个问题的答案
Fattie

4
我不明白...这段代码永远不会让任何东西都被选中。
C. Tewalt

@matrixugly是正确的。在内部执行此操作更合适willSelectRowAt:。在这里看到更完整的答案:stackoverflow.com/questions/12693402/…–
HuaTham

117

在表视图委托的didSelectRowAtIndexpath(或从任何地方)中使用以下方法

[myTable deselectRowAtIndexPath:[myTable indexPathForSelectedRow] animated:YES];

2
值得注意的是,这indexPathForSelectedRow是方法而不是属性。
FreeAsInBeer

甜!不知道[myTable indexPathForSelectedRow]。我之前遍历了牢房。谢谢!
guptron

@FreeAsInBeer这种区别在某种程度上重要吗?属性访问器是方法。
devios1 2013年

@chaiguy如果您不介意同事认为您是邪恶的,那很好。
FreeAsInBeer 2013年

1
@Supertecnoboff两种变体之间的性能没有差异。
FreeAsInBeer '16

38

试试这个:

for (NSIndexPath *indexPath in tableView.indexPathsForSelectedRows) {
    [tableView deselectRowAtIndexPath:indexPath animated:NO];
}

1
干得好...我认为第二行的“索引”应该是indexPath
El Tomato

这是不支持iOS 11斯威夫特4
鲍里斯·尼科利奇

30

为此,在Swift中进行扩展可能会很有用。

Swift 4和Swift 5:

Swift扩展(例如,在UITableViewExtension.swift文件中):

import UIKit

extension UITableView {

    func deselectSelectedRow(animated: Bool)
    {
        if let indexPathForSelectedRow = self.indexPathForSelectedRow {
            self.deselectRow(at: indexPathForSelectedRow, animated: animated)
        }
    }

}

使用例如:

override func viewWillAppear(_ animated: Bool)
{
    super.viewWillAppear(animated)

    self.tableView.deselectSelectedRow(animated: true)
}

1
我认为,此答案更好,因为将荒凉的viewWillAppear()方法放入方法中可以帮助用户了解他从何而来。
MonsieurDart

我所需要的完美作品
Patel Jigar

28

请使用委托方法检查是否正确。例如;

-(void) tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath

对于

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

一直以来都在调用错误的方法,啊!谢谢!
Damir Kotoric 2014年

1
哦,伙计...。血腥的自动补全!!!我花了几个小时才弄清楚!!!天哪...我想吻你!
乔治·阿斯达


16

这是Swift 4的解决方案

 in tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)

只需添加

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

它就像一个魅力

例:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
//some code
}

除非您在
表格视图中

这肯定是正确的方法,当您不进行编辑时,或者当您“轻按一行以做某事”时
Fattie

11

除了将单元格设置为选中状态之外,还需要通知tableView该单元格已选中。将调用添加-tableView:selectRowAtIndexPath:animated:scrollPosition:到您的willDisplayCell:方法:您将可以照常取消选择它。

- (void)tableView:(UITableView*)tableView 
  willDisplayCell:(UITableViewCell*)cell
forRowAtIndexPath:(NSIndexPath*)indexPath
{ 
    AppDelegate_iPad *appDelegte = (AppDelegate_iPad *)[[UIApplication sharedApplication] delegate];

    if ([appDelegte.indexPathDelegate row] == [indexPath row])
    {
        // SELECT CELL
        [cell setSelected:YES]; 
        // TELL TABLEVIEW THAT ROW IS SELECTED
        [tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];   
    } 
}

请确保使用UITableViewScrollPositionNone以避免奇怪的滚动行为。


1
完全正确。我认为[cell setSelected:YES]可以省略:selectRowAtIndexPath将照顾细胞selected状态
spassas

此答案适用于具有多个选择的UITableView。竖起大拇指。
丹尼·布拉沃

6

这应该工作:

[tableView deselectRowAtIndexPath:indexpath1 animated:NO];

只要确保materialTable和tableView指向同一对象即可。

材料是否已连接到Interface Builder中的tableView?


我已经测试过,但是也不能解决我的问题。但是我用另一种方法解决了这个问题,因为当didselect委托被解雇时,重新加载了数据。
拉姆

6

基于saikirans解决方案,我写了这篇文章,对我有帮助。在.m文件上:

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

    if(selectedRowIndex && indexPath.row == selectedRowIndex.row) {

        [tableView deselectRowAtIndexPath:indexPath animated:YES];
        selectedRowIndex = nil;

    }

    else {  self.selectedRowIndex = [indexPath retain];   }

    [tableView beginUpdates];
    [tableView endUpdates];

}

并在头文件上:

@property (retain, nonatomic) NSIndexPath* selectedRowIndex;

我也不是很有经验,所以请仔细检查内存泄漏等。


6

如果要通过第一次单击选择任何表单元格,然后通过第二次单击取消选择,则应使用以下代码:

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

    if (self.selectedIndexPath && 
        [indexPath compare:self.selectedIndexPath] == NSOrderedSame) {

        [tableView deselectRowAtIndexPath:indexPath animated:YES];
         self.selectedIndexPath = nil;
    } 
    else {
        self.selectedIndexPath = indexPath;
    }
}

5

斯威夫特4:

func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
    let cell = tableView.cellForRow(at: indexPath)
    if cell?.isSelected == true { // check if cell has been previously selected
        tableView.deselectRow(at: indexPath, animated: true)
        return nil
    } else {
        return indexPath
    }
}

2
这斯威夫特3只为我工作不得不添加self.tableView(tableView, didDeselectRowAt: indexPath)tableView.deselectRow...,因为它不是自动调用
elysch


3

试试这个

[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];

尝试解释您的答案,否则应为评论。
雨果·多佐伊斯

3
NSIndexPath * index = [self.menuTableView indexPathForSelectedRow];
[self.menuTableView deselectRowAtIndexPath:index animated:NO];

根据您的代码放置此代码,您将取消选择单元格。


3

你可以试试看吗?

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

    AppDelegate_iPad *appDelegte = 
    (AppDelegate_iPad *)[[UIApplication sharedApplication] delegate];
    NSIndexPath *indexpath1 = appDelegte.indexPathDelegate;
    appDelegte.indexPathDelegate = indexPath;

    UITableViewCell *prevSelectedCell = [tableView cellForRowAtIndexPath: indexpath1];
    if([prevSelectedCell isSelected]){
       [prevSelectedCell setSelected:NO];
    }
}

它为我工作。


2

Swift 3.0:

遵循ray wenderlich swift样式指南协议一致性部分,为将相关方法分组在一起,请将此扩展名如下放置在视图控制器类下面:

// your view controller
class MyViewcontroller: UIViewController {
  // class stuff here
}

// MARK: - UITableViewDelegate
extension MyViewcontroller: UITableViewDelegate {
      // use the UITableViewDelegate method tableView(_:didSelectRowAt:)
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

        // your code when user select row at indexPath

        // at the end use deselectRow
        tableView.deselectRow(at: indexPath, animated: true)
    }
}

1

迅速

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

    // your code

    // your code

    // and use deselect row to end line of this function

    self.tableView.deselectRowAtIndexPath(indexPath, animated: true)

}

1
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    tableView.deselectRow(at: indexPath, animated: true)
}

1

迅捷3

我也碰到过这一点-当您导航或退回到表格视图时,它通常不会为您取消选择先前选择的行。我将此代码放在表格视图控制器中,并且效果很好:

override func viewDidAppear(_ animated: Bool) {
    if let lastSelectedRow = tableView.indexPathForSelectedRow {
        tableView.deselectRow(at: lastSelectedRow, animated: true)
    }
}

1

迅捷3/4

在ViewController中:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    tableView.deselectRow(at: indexPath, animated: true)
}

在自定义单元格中:

override func awakeFromNib() {
    super.awakeFromNib()
    selectionStyle = .none
}


0

由于预加载的数据,第一次单击时取消选择(DidDeselectRowAt)会触发;您需要通知tableView该行已被选择为开始,以便单击一次即可取消选择该行:

//迅速3:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    if tableView[indexPath.row] == "data value"

        tableView.selectRow(at: indexPath, animated: false, scrollPosition: UITableViewScrollPosition.none)

    }
}

0

我发现,除了将单元格设置为selected之外,还必须让表视图知道如何在给定的索引路径下选择行。

// Swift 3+  

override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    if appDelegate.indexPathDelegate.row == indexPath.row {
        self.tableView.selectRow(at: indexPath, animated: true, scrollPosition: .none)
        cell.setSelected(true, animated: true)
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.