Tại sao UITableViewCell vẫn được tô sáng?


145

Điều gì sẽ khiến một ô xem bảng vẫn được tô sáng sau khi được chạm vào? Tôi bấm vào ô và có thể thấy nó vẫn được tô sáng khi chế độ xem chi tiết được đẩy. Khi chế độ xem chi tiết được bật, ô vẫn được tô sáng.

Câu trả lời:


262

Trong didSelectRowAtIndexPathbạn cần gọi deselectRowAtIndexPathđể bỏ chọn ô.

Vì vậy, bất cứ điều gì khác bạn đang làm trong didSelectRowAtIndexPathbạn chỉ cần có nó deselectRowAtIndexPathlà tốt.

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

11
Tôi thích gọi deselectRowAtIndexPathtrong viewDidAppear của tôi, nếu chọn hàng sẽ hiển thị một chế độ xem mới.
không có

5
Trên thực tế, đó không phải là nơi thích hợp để gọi nó, thực sự ... hãy thử sử dụng ứng dụng Apple có bảng (Danh bạ là một ứng dụng tốt) và bạn sẽ thấy sau khi bạn đẩy ra màn hình mới, khi trả về, ô vẫn được tô sáng một thời gian ngắn trước khi được bỏ chọn. Về lý thuyết, tôi nghĩ rằng bạn không cần phải thực hiện thêm bất kỳ công việc nào để tự mình bỏ chọn ngay lập tức, vì vậy không nên sử dụng mã trong viewDidAppear ...
Kendall Helmstetter Gelner

6
@Kendall, @ 4thSpace: Có thể bình luận cuối cùng của tôi đã gây nhầm lẫn về việc tôi đang đề cập đến ai, xin lỗi vì điều đó. UITableViewControll gọi -deselectRowAtIndexPath:animated:phương thức trên thuộc tính tableView của nó từ -viewDidAppear. Tuy nhiên, nếu bạn có chế độ xem bảng trong lớp con UIViewControll, bạn nên gọi -deselectRowAtIndexPath:animated:từ -viewDidAppearchính mình. :)
Daniel Tull

5
Trong lớp con của UITableViewCont kiểm soát của tôi, nó thực sự là một ghi đè của -viewWillAppear:nó đã phá vỡ nó. Thêm một cuộc gọi để làm cho [super viewWillAppear:animated]nó hoạt động trở lại.
Ben Challenor

5
Kể từ 3.2, các hành vi deselection tự động xảy ra nếu bạn UITableViewController's clearsSelectionOnViewWillAppeartài sản được thiết lập để YES(đó là mặc định), và bạn đã không ngăn cản [super viewWillAppear]khỏi bị gọi.
Chống phân mảnh

62

Cách rõ ràng nhất để làm điều đó là trên viewWillAppear:

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

Bằng cách này, bạn có hình ảnh động mờ dần lựa chọn khi bạn quay lại bộ điều khiển, như nó phải vậy.

Lấy từ http://forums.macrumors.com/showthread.php?t=577677

Phiên bản Swift

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
Đây là thứ mà tôi mong đợi hầu hết mọi người sẽ muốn nếu họ không sử dụng UITableViewControll. +1
MikeB

3
Tôi tự hỏi mọi người đang làm gì bây giờ khi iOS 7 cho phép người dùng 'kéo' lại. Kéo một phần nhưng sau đó không hoàn thành hành động sẽ kích hoạt viewWillAppear. Khi người dùng trả về thực, hàng sẽ không được chọn.
Ben Packard

1
@BenPackard chỉ cần gọi nó vào viewDidAppearthay thế.
Squarefrog

@Jessica Cuộc indexPathForSelectedRowgọi có thể trả về nil vì vậy cần kiểm tra lại. Tài liệu nêu rõ : Đường dẫn chỉ mục xác định chỉ mục hàng và phần của hàng đã chọn hoặc không nếu đường dẫn chỉ mục không hợp lệ.
Gordonium

điều này đáng chú ý là câu trả lời được chấp nhận, nó thân thiện với giao diện người dùng hơn để người dùng có thể tiếp cận lựa chọn sau khi quay lại, hoàn hảo
Yahya Alshaar

20

Bạn đã phân lớp -(void)viewWillAppear:(BOOL)animated? UITableViewCell đã chọn sẽ không bỏ chọn khi bạn không gọi [super viewWillAppear:animated];trong phương thức tùy chỉnh của mình.


19

Đối với người dùng Swift, hãy thêm mã này vào mã của bạn:

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

Đó là câu trả lời của paulthenerd ngoại trừ trong Swift thay vì Obj-C.


1
Không phải nó bị bỏ qua bởi chính nó, ý tôi là khoảnh khắc bạn buông tay?
Mật ong

@Honey Có thể như vậy trong một phiên bản iOS trước, hoặc khi chế độ xem biến mất, nhưng chắc chắn không phải bây giờ trong iOS 10 (có thể thậm chí sớm hơn) và cao hơn.
Jamie Birch

9

Giải pháp Swift 3

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

7

Nếu bạn đang sử dụng UITableViewCell, hãy bình luận dòng sau

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

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

}

Hi vọng điêu nay co ich.


4

Cập nhật với Swift 4

Sau một vài thử nghiệm, cũng dựa trên các câu trả lời trước đó, tôi đã có kết luận rằng hành vi tốt nhất có thể đạt được theo 2 cách: (gần như giống hệt nhau trong thực tế)

// 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)
    }
}

Cá nhân tôi đang áp dụng giải pháp đầu tiên, vì đơn giản là nó ngắn gọn hơn. Một khả năng khác, nếu bạn cần một hình ảnh động nhỏ khi bạn quay lại bảngView, là sử dụng 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)
    }
}

Cuối cùng nhưng không kém phần quan trọng, nếu bạn đang sử dụng UITableViewCont kiểm soát, bạn cũng có thể tận dụng lợi thế của thuộc tính xóaSelectionOnViewWillAppear .


3

Để có được hành vi mà Kendall Helmstetter Gelner mô tả trong bình luận của mình, bạn có thể không muốn deselectRowAtIndexPath mà thay vào đó là thuộc tính ClearsSelectionOnViewWillAppear trên bộ điều khiển của bạn. Có lẽ điều này đã được đặt thành CÓ một cách tình cờ?

Xem bình luận trong mẫu Apple mặc định cho các lớp con UITableViewControll mới:

- (void)viewDidLoad
{
    [super viewDidLoad];

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

2

Tôi đã nhận được vấn đề này cũng như cho ứng dụng đi sâu của tôi. Sau một trình điều khiển khung nhìn, mà tôi sẽ gọi VC, trả về sau khi đẩy một ViewContoder khác, ô được chọn trong VC vẫn được tô sáng. Trong ứng dụng của mình, tôi đã tạo ra VC để xử lý cấp độ thứ hai (trong số ba cấp độ) trong quá trình truy sâu của tôi.

Vấn đề trong trường hợp của tôi là VC là một UIViewContoder (có chứa Chế độ xem có chứa TableView). Thay vào đó, tôi đã biến VC thành UITableViewControll (có chứa TableView). Lớp UITableViewCont kiểm soát tự động xử lý khử sáng của ô bảng sau khi trở về từ một lần đẩy. Câu trả lời thứ hai cho bài viết " Vấn đề với deselectRowAtIndexPath trong bảngView " đưa ra câu trả lời đầy đủ hơn cho vấn đề này.

Sự cố không xảy ra đối với trình điều khiển xem gốc vì khi tôi tạo ứng dụng dưới dạng "Ứng dụng dựa trên điều hướng" trong XCode, trình điều khiển xem gốc đã được tạo cho lớp con UITableViewContaptor.


1

Nếu không có cách nào trong số này phù hợp với bạn, hãy xem xét cách giải quyết này:

Sử dụng một segue thư giãn để gọi:

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

Tại sao làm điều này? Chủ yếu nếu bạn gặp khó khăn khi lấy mã bỏ chọn để chạy đúng lúc. Tôi gặp sự cố với nó không hoạt động trên viewWillAppear vì vậy thư giãn hoạt động tốt hơn rất nhiều.

Các bước:

  1. Viết segue thư giãn (hoặc dán từ trên xuống) vào VC đầu tiên của bạn (cái có bảng)

  2. Chuyển đến VC thứ 2. Điều khiển kéo từ nút Hủy / Xong / Vv mà bạn đang sử dụng để loại bỏ VC đó và kéo đến Biểu tượng Thoát ở trên cùng.

  3. Chọn segue thư giãn bạn đã tạo ở bước 1

    Chúc may mắn.


Đây là giải pháp tốt nhất cho thời gian khi viewDidAppear không kích hoạt (nghĩa là nếu chế độ xem con được trình bày dưới dạng biểu mẫu và không bao phủ toàn màn hình).
pheedsta

1

Tôi đang sử dụng CoreData vì vậy mã làm việc cho tôi là sự kết hợp các ý tưởng từ nhiều câu trả lời khác nhau, trong Swift:

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

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

0

Tôi đã có cùng một vấn đề trong một thời gian dài vì vậy trong trường hợp có ai khác đang vật lộn:

Hãy nhìn vào của bạn -tableView: cellForRowAtIndexPath: và xem nếu bạn đang tạo các ô hoặc sử dụng 'định danh tái sử dụng'. Nếu sau này, hãy chắc chắn rằng bảng của bạn trong IB có một ô có mã định danh đó. Nếu bạn không sử dụng Mã định danh tái sử dụng, chỉ cần tạo một ô mới cho mỗi hàng.

Điều này sau đó sẽ cung cấp cho bảng của bạn 'hàng được chọn mờ' dự kiến ​​xuất hiện.


0

Sử dụng phương thức này trong lớp UITableViewCell

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

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

0

Đối với Swift 3: Tôi muốn sử dụng nó trong viewDidDisappear

Định nghĩa:-

    var selectedIndexPath = IndexPath()

Trong viewDidDisappear: -

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

Trong didSelectRowAtIndexPath: -

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

0

nếu ô còn lại được tô sáng sau khi chạm vào nó, bạn có thể gọi phương thức UITabelView,

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

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

}

Hoặc, bạn có thể sử dụng phương pháp sau và sửa đổi nó theo yêu cầu của bạn,

// Đánh dấu: 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

Tôi gặp vấn đề tương tự và phát hiện ra tôi đã để lại một cuộc gọi trống để xemWillAppear ở cuối bảngViewControll của tôi. Khi tôi loại bỏ chức năng ghi đè trống, hàng không còn được tô sáng khi quay lại chế độ xem bảng.

vấn đề

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

loại bỏ chức năng trống đã giải quyết vấn đề của tôi.


0

Giải pháp Swift 5:

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    tableView.deselectRow(at: indexPath as IndexPath, animated: true)
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.