ทำไม UITableViewCell ยังคงเน้นอยู่


145

อะไรจะทำให้เซลล์มุมมองตารางยังคงเน้นอยู่หลังจากถูกสัมผัส ฉันคลิกเซลล์และสามารถดูว่าไฮไลต์อยู่เมื่อมีการผลักมุมมองรายละเอียด เมื่อมุมมองรายละเอียดปรากฏขึ้นเซลล์จะยังคงเน้นอยู่

คำตอบ:


262

ในของdidSelectRowAtIndexPathคุณคุณต้องโทรdeselectRowAtIndexPathเพื่อยกเลิกการเลือกเซลล์

ดังนั้นสิ่งที่คุณกำลังทำอยู่ในตัวdidSelectRowAtIndexPathคุณก็แค่เรียกมันdeselectRowAtIndexPathเช่นกัน

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
 // Do some stuff when the row is selected
 [tableView deselectRowAtIndexPath:indexPath animated:YES];
}

11
ฉันชอบโทรdeselectRowAtIndexPathใน viewDidAppear ของฉันหากเลือกแถวจะแสดงมุมมองใหม่
notnoop

5
จริง ๆ แล้วมันไม่ใช่สถานที่ที่เหมาะสมที่จะโทรหาจริงๆ ... ลองใช้แอป Apple กับตาราง (ที่ติดต่อเป็นสิ่งที่ดี) และคุณจะเห็นหลังจากที่คุณผลักออกไปที่หน้าจอใหม่เมื่อเซลล์กลับมาก็ยังคงเน้นอยู่ สั้น ๆ ก่อนที่จะถูกยกเลิกการเลือก ในทางทฤษฎีฉันคิดว่าคุณไม่จำเป็นต้องทำงานพิเศษใด ๆ เพื่อยกเลิกการเลือกในทันทีดังนั้นจึงไม่จำเป็นต้องใช้โค้ดใน viewDidAppear ...
Kendall Helmstetter Gelner

6
@ เคนดอล, @ 4thSpace: บางทีความคิดเห็นสุดท้ายของฉันอาจสับสนว่าฉันเป็นใครพูดถึงขอโทษสำหรับสิ่งที่ UITableViewController เรียก-deselectRowAtIndexPath:animated:วิธีการเกี่ยวกับทรัพย์สิน tableView -viewDidAppearจาก อย่างไรก็ตามหากคุณมีมุมมองตารางในคลาสย่อย UIViewController คุณควรโทร-deselectRowAtIndexPath:animated:จาก-viewDidAppearตัวคุณเอง :)
Daniel Tull

5
ใน subclass ของฉันของ UITableViewController จริงๆแล้วมันเป็นการแทนที่ของ-viewWillAppear:ที่มันพัง เพิ่มการเรียกเพื่อให้[super viewWillAppear:animated]มันทำงานอีกครั้ง
Ben Challenor

5
ตั้งแต่ 3.2 พฤติกรรมไม่เลือกอัตโนมัติเกิดขึ้นหากคุณUITableViewController's clearsSelectionOnViewWillAppearตั้งค่าคุณสมบัติYES(ซึ่งเป็นค่าเริ่มต้น) และคุณยังไม่สามารถป้องกัน[super viewWillAppear]จากการถูกเรียกว่า
ระเบียบข้อมูล

62

วิธีที่สะอาดที่สุดที่จะทำคือดูได้ดังนี้:

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    // Unselect the selected row if any
    NSIndexPath*    selection = [self.tableView indexPathForSelectedRow];
    if (selection) {
        [self.tableView deselectRowAtIndexPath:selection animated:YES];
    }
}

วิธีนี้คุณจะมีภาพเคลื่อนไหวของการลบการเลือกเมื่อคุณกลับไปที่คอนโทรลเลอร์ตามที่ควรจะเป็น

นำมาจากhttp://forums.macrumors.com/showthread.php?t=577677

รุ่นที่รวดเร็ว

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

    // deselect the selected row if any
    let selectedRow: IndexPath? = tableView.indexPathForSelectedRow
    if let selectedRowNotNill = selectedRow {
        tableView.deselectRow(at: selectedRowNotNill, animated: true)
    }
}

1
นี่คือสิ่งที่ฉันคาดหวังว่าคนส่วนใหญ่จะต้องการหากพวกเขาไม่ได้ใช้ UITableViewController +1
MikeB

3
ฉันสงสัยว่าผู้คนกำลังทำอะไรอยู่ตอนนี้ที่ iOS 7 อนุญาตให้ผู้ใช้ 'ลาก' ย้อนกลับ การลากบางส่วน แต่ไม่เสร็จสิ้นการดำเนินการจะทำให้มุมมอง WillAppear เมื่อผู้ใช้ส่งกลับค่าจริงแถวจะไม่ถูกเลือก
Ben Packard

1
@ BenPackard เพียงแค่เรียกมันมาviewDidAppearแทน
squarefrog

@Jessica การindexPathForSelectedRowโทรสามารถส่งคืนศูนย์ดังนั้นควรตรวจสอบ สถานะเอกสารคู่มือ : เส้นทางดัชนีระบุแถวและดัชนีส่วนของแถวที่เลือกหรือไม่มีถ้าเส้นทางดัชนีไม่ถูกต้อง
Gordonium

นี่ควรพูดว่าเป็นคำตอบที่ยอมรับมันเป็นมิตรกับ UI มากกว่าดังนั้นผู้ใช้สามารถเข้าถึงตัวเลือกหลังจากกลับมาสมบูรณ์แบบ👌
Yahya Alshaar

20

คุณคลาสย่อย-(void)viewWillAppear:(BOOL)animatedหรือไม่ UITableViewCell ที่เลือกจะไม่ยกเลิกการเลือกเมื่อคุณไม่ได้โทร[super viewWillAppear:animated];ด้วยวิธีการที่กำหนดเองของคุณ


19

สำหรับผู้ใช้ Swift เพิ่มรหัสของคุณ:

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    tableView.deselectRowAtIndexPath(indexPath, animated: true)
}

มันเป็นคำตอบของ paulthenerd ยกเว้นใน Swift แทนที่จะเป็น Obj-C


1
มันไม่ถูกยกเลิกโดยตัวเองฉันหมายถึงช่วงเวลาที่คุณปล่อย
ฮันนี่

@Honey อาจเป็นไปได้ว่าใน iOS เวอร์ชันก่อนหน้าหรือตามที่ดูหายไป แต่ตอนนี้ยังไม่แน่นอนใน iOS 10 (น่าจะถึงก่อนหน้านี้) และสูงกว่า
เจมี่เบิร์ช


7

หากคุณใช้ UITableViewCell ให้คอมเม้นต์บรรทัดต่อไปนี้

- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{

 // [super setSelected:selected animated:animated];

}

หวังว่านี่จะช่วยได้


4

อัปเดตด้วย Swift 4

หลังจากการทดลองสองสามครั้งโดยใช้คำตอบก่อนหน้านี้ฉันได้ข้อสรุปว่าพฤติกรรมที่ดีที่สุดสามารถทำได้ 2 วิธี: (เกือบเหมือนกันในทางปฏิบัติ)

// First Solution: delegate of the table View
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    tableView.deselectRow(at: indexPath, animated: false)
}

// Second Solution: With the life cycle of the view.
override func viewDidDisappear(_ animated: Bool) {
    super.viewDidDisappear(animated)

    let selectedRow: IndexPath? = tableView.indexPathForSelectedRow
    if let selectedRow = selectedRow {
        tableView.deselectRow(at: selectedRow, animated: false)
    }
}

ฉันใช้วิธีแรกเป็นการส่วนตัวเพราะมันเป็นเรื่องง่ายกว่า ความเป็นไปได้อีกประการหนึ่งหากคุณต้องการภาพเคลื่อนไหวเล็ก ๆ น้อย ๆ เมื่อคุณกลับไปที่ tableView คุณต้องใช้viewWillAppear:

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

    let selectedRow: IndexPath? = _view.tableView.indexPathForSelectedRow
    if let selectedRow = selectedRow {
        _view.tableView.deselectRow(at: selectedRow, animated: true)
    }
}

สุดท้าย แต่ไม่ท้ายสุดถ้าคุณใช้ UITableViewController คุณสามารถใช้ประโยชน์จากคุณสมบัติเคลียร์ SelectSOnViewWillAppear


3

เพื่อให้ได้พฤติกรรม Kendall Helmstetter Gelner อธิบายในความคิดเห็นของเขาคุณอาจไม่ต้องการ deselectRowAtIndexPath แต่ควรจะล้างคุณสมบัติSelectionOnViewWillAppearบนคอนโทรลเลอร์ของคุณ บางทีนี่อาจถูกตั้งค่าเป็นใช่โดยบังเอิญ?

ดูความคิดเห็นในเทมเพลต Apple ที่เป็นค่าเริ่มต้นสำหรับคลาสย่อย UITableViewController ใหม่:

- (void)viewDidLoad
{
    [super viewDidLoad];

    // Uncomment the following line to preserve selection between presentations.
    // self.clearsSelectionOnViewWillAppear = NO;
}

2

ฉันได้รับปัญหานี้เช่นกันสำหรับแอปพลิเคชันเจาะลึก หลังจาก viewcontroller ซึ่งฉันจะเรียก VC กลับมาหลังจากกด ViewController อื่นเซลล์ที่เลือกใน VC ยังคงเน้นอยู่ ในแอพของฉันฉันได้สร้าง VC เพื่อจัดการระดับที่สอง (จากสามระดับ) ของการเจาะลึกของฉัน

ปัญหาในกรณีของฉันคือ VC เป็น UIViewController (ที่มีมุมมองที่มี TableView) ฉันทำ VC เป็น UITableViewController (ที่มี TableView) แทน คลาส UITableViewController จัดการการไฮไลต์ของเซลล์ตารางโดยอัตโนมัติหลังจากกลับมาจากการกด คำตอบที่สองสำหรับการโพสต์ " ปัญหาเกี่ยวกับ deselectRowAtIndexPath ใน tableView " ให้คำตอบที่สมบูรณ์ยิ่งขึ้นสำหรับปัญหานี้

ปัญหาไม่ได้เกิดขึ้นกับ root viewcontroller เพราะเมื่อฉันสร้างแอปเป็น "แอพที่ใช้การนำทาง" ใน XCode ตัวควบคุมรูทที่ได้ทำให้ผลลัพธ์นั้นได้ทำการ subclass UITableViewController แล้ว


1

หากคุณไม่เห็นด้วยกับสิ่งเหล่านี้

ใช้การผ่อนคลายเพื่อโทร:

@IBAction func unwind_ToTableVC (segue: UIStoryboardSegue) {
    if let index = tableView.indexPathForSelectedRow {
        tableView.deselectRowAtIndexPath(index, animated: true)
    }
}

ทำไมต้องทำเช่นนี้? หลักถ้าคุณมีปัญหาในการรับรหัสยกเลิกการเลือกให้ทำงานในเวลาที่เหมาะสม ฉันมีปัญหากับมันไม่ทำงานในมุมมอง WillAppear ดังนั้นการผ่อนคลายก็ทำงานได้ดีขึ้นมาก

ขั้นตอน:

  1. เขียนการแบ่งการคลาย (หรือวางจากด้านบน) ลงใน VC แรกของคุณ (อันที่มีโต๊ะ)

  2. ไปที่ VC ที่ 2 ควบคุมการลากจากปุ่มยกเลิก / เสร็จสิ้น / อื่น ๆ ที่คุณใช้เพื่อยกเลิก VC และลากไปที่ไอคอนออกที่ด้านบน

  3. เลือกชุดการคลายที่คุณสร้างในขั้นตอนที่ 1

    โชคดี.


นี่เป็นทางออกที่ดีที่สุดสำหรับเวลาที่ viewDidAppear ไม่เริ่มทำงาน (เช่นถ้ามุมมองลูกถูกแสดงแบบฟอร์มเป็นแบบฟอร์มและไม่ครอบคลุมทั้งหน้าจอ)
pheedsta

1

ฉันใช้ CoreData ดังนั้นรหัสที่ใช้งานได้สำหรับฉันคือการผสมผสานความคิดจากคำตอบต่าง ๆ ใน Swift:

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


0

ฉันมีปัญหาเดียวกันมานานแล้วดังนั้นในกรณีที่มีคนอื่นกำลังดิ้นรน

ดูที่ของคุณ-tableView: cellForRowAtIndexPath:และดูว่าคุณกำลังสร้างเซลล์หรือใช้ 'ตัวระบุการใช้ซ้ำ' หากหลังตรวจสอบให้แน่ใจว่าตารางของคุณใน IB มีเซลล์พร้อมตัวระบุนั้น หากคุณไม่ได้ใช้ตัวระบุซ้ำเพียงแค่สร้างเซลล์ใหม่สำหรับแต่ละแถว

สิ่งนี้จะทำให้ตารางของคุณ 'จางแถวที่เลือก' ที่คาดหวังเมื่อปรากฏ


0

ใช้วิธีนี้ในคลาส UITableViewCell

- (void)setSelected:(BOOL)selected animated:(BOOL)animated {

   // Just comment This line of code
   // [super setSelected:selected animated:animated];        
}

0

สำหรับ Swift 3: ฉันต้องการใช้ใน viewDidDisappear

กำหนด:-

    var selectedIndexPath = IndexPath()

ใน viewDidDisappear: -

    override func viewDidDisappear(_ animated: Bool) {
    yourTableView.deselectRow(at: selectedIndexPath, animated: true)
}

ใน didSelectRowAtIndexPath: -

    func tableView(_ tableView: UITableView, didSelectRowAtIndexPath indexPath: IndexPath) {
    selectedIndexPath = indexPath
}

0

หากเซลล์ยังคงไฮไลต์อยู่หลังจากแตะคุณสามารถเรียกใช้วิธี UITabelView

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

`[tableView deselectRowAtIndexPath:indexPath animated:YES];`   

}

หรือคุณสามารถใช้วิธีการต่อไปนี้และแก้ไขตามความต้องการของคุณ

// MARK: UITableViewDelegate

func tableView(tableView: UITableView, didHighlightRowAtIndexPath indexPath: NSIndexPath) {
  if let cell = tableView.cellForRowAtIndexPath(indexPath) {
     cell.backgroundColor = UIColor.greenColor()
  }
}

func tableView(tableView: UITableView, didUnhighlightRowAtIndexPath indexPath: NSIndexPath) {
  if let cell = tableView.cellForRowAtIndexPath(indexPath) {
     cell.backgroundColor = UIColor.blackColor()
  }
} 

0

Xcode 10, Swift 4

ฉันมีปัญหาเดียวกันนี้และค้นพบว่าฉันออกจากสายที่ว่างเปล่าเพื่อดู WillAppear ที่ด้านล่างของ tableViewController ของฉัน เมื่อฉันลบฟังก์ชั่นการแทนที่ที่ว่างเปล่าแถวนั้นจะไม่ถูกเน้นอีกเมื่อกลับสู่มุมมอง tableView

ปัญหา func

override func viewWillAppear(_ animated: Bool) {
  // need to remove this function if not being used.
}

ลบฟังก์ชั่นที่ว่างเปล่าแก้ปัญหาของฉัน


0

โซลูชัน Swift 5:

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    tableView.deselectRow(at: indexPath as IndexPath, animated: true)
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.