วิธียกเลิกการเลือกเซลล์ 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

คำตอบ:


407

ใช้รหัสนี้

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

สวิฟท์ 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

3
ผมชอบที่จะคิดว่าฉันไม่สามารถ upvote โพสต์นี้เพราะมันจะทำให้เกิดการล้นจำนวนเต็ม :)
ไมโล

สวัสดี @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 ความแตกต่างนี้มีความสำคัญหรือไม่? accessors เป็นวิธีการ
devios1

@chaiguy ที่ดีหากคุณไม่ทราบเพื่อนร่วมงานของคุณพิจารณาคุณชั่วร้าย
FreeAsInBeer

1
@Supertecnoboff ไม่มีความแตกต่างของประสิทธิภาพระหว่างสองรูปแบบ
FreeAsInBeer

38

ลองสิ่งนี้:

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

1
ดีมาก ... ฉันคิดว่า 'ดัชนี' ในบรรทัดที่ 2 ควรเป็น indexPath
El Tomato

สิ่งนี้ไม่รองรับบน iOS 11 Swift 4
Boris Nikolic

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

หนึ่งที่สมบูรณ์แบบที่ฉันจำเป็น
เทล Jigar

28

โปรดตรวจสอบกับวิธีการมอบหมายว่าถูกต้องหรือไม่ ตัวอย่างเช่น;

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

สำหรับ

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

เรียกวิธีการที่ไม่ถูกต้องตลอดเวลานี้เถอะ !! ขอบคุณ!
Damir Kotoric

1
โอ้มนุษย์ .... การเติมข้อความอัตโนมัตินองเลือด !!! ฉันใช้เวลาหลายชั่วโมงกว่าจะเข้าใจ !!! OMG ... ฉันต้องการจูบคุณ!
George Asda

22

สวิฟท์ 4:

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

ไม่จำเป็นต้องประกาศว่าไม่ใช่ตัวเลือก แต่ถูกต้อง
Michael

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
}

จนกว่าคุณจะเพิ่มการเลือกในการแก้ไขใน tableview ของคุณมันจะเป็นไปไม่ได้ที่จะเลือกเซลล์ใด ๆ เพราะมันจะยกเลิกการเลือกเมื่อคุณเลือกเสร็จ :)
Mehdi Chennoufi

นี่เป็นวิธีที่ถูกต้องเมื่อคุณไม่ได้แก้ไขเมื่อคุณ "แตะแถวเพื่อทำอะไรบางอย่าง"
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สถานะของเซลล์
ปาส

คำตอบนี้ใช้ได้กับ UITableView ด้วยการเลือกหลายแบบ ยกนิ้ว
Danny Bravo

6

สิ่งนี้น่าจะใช้ได้:

[tableView deselectRowAtIndexPath:indexpath1 animated:NO];

เพียงให้แน่ใจว่า materialTable และ tableView ชี้ไปที่วัตถุเดียวกัน

วัสดุเชื่อมต่อกับ 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
สิ่งนี้ใช้ได้กับฉันใน Swift 3 เพียงแค่ต้องเพิ่มself.tableView(tableView, didDeselectRowAt: indexPath)หลังจากนั้นtableView.deselectRow...เพราะมันไม่ได้ถูกเรียกโดยอัตโนมัติ
elysch


3

ลองนี้

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

ลองอธิบายคำตอบของคุณมิฉะนั้นควรเป็นความคิดเห็น
Hugo Dozois

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

สวิฟท์ 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

สวิฟท์ 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 ว่าแถวนั้นถูกเลือกไว้แล้วเพื่อเริ่มต้นด้วยดังนั้นการคลิกครั้งแรกจากนั้นจึงยกเลิกการเลือกแถว:

// Swift 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

สิ่งที่ฉันได้พบคือที่ด้านบนของการตั้งค่าเซลล์ตามที่เลือกคุณต้องแจ้งให้มุมมองตารางเพื่อเลือกแถวที่พา ธ ดัชนีที่กำหนด

// 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)
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.