UITableView: viewForHeaderInSection: không được gọi trong quá trình reloadData:


127

Tôi đã thiết lập chế độ xem bảng với các liên kết nguồn và dữ liệu chính xác .. phương thức reloadData gọi nguồn dữ liệu và phương thức ủy nhiệm ngoại trừ viewForHeaderInSection:.

Tại sao lại như vậy?


30
heightForHeaderInSection:thực hiện?
7 giờ sáng

Bạn đã đặt giá trị cho TableView sectionHeaderHeightchưa?
Carter Medlin

Câu trả lời:


256

Việc sử dụng tableView:viewForHeaderInSection:đòi hỏi bạn cũng phải thực hiện tableView:heightForHeaderInSection:. Điều này sẽ trả về một chiều cao khác không thích hợp cho tiêu đề. Ngoài ra hãy chắc chắn rằng bạn không còn thực hiện tableView:titleForHeaderInSection:. Bạn chỉ nên sử dụng cái này hoặc cái kia ( viewForHeaderhoặc titleForHeader).


3
Hãy chắc chắn rằng không có lỗi đánh máy trong chữ ký của phương thức. Một chữ cái sai sẽ có nghĩa là nó sẽ không được gọi. Kiểm tra trường hợp quá. Cũng chắc chắn rằng bạn đang trở về 0 từ numberOfSections.
rmaddy

mọi thứ đều chính xác và biên dịch chính xác .. vấn đề tôi muốn hiểu là xung quanh thời điểm khi phương thức được gọi .. bảngView: viewForHeaderInSection được gọi khi bảng sắp được hiển thị và không phải là một phần của việc thực thi đồng bộ của [ tableview reloadData]
inforeqd

@maddy OMG Cảm ơn bạn, thật ngu ngốc với tôi, tôi đã tạo ra các trường hợp của mình nhưng tôi đã không nối vào mảng của mình
Happiehappie

4
Bạn hoàn toàn có thể có cả hai. viewForHeaderInSection: sẽ được ưu tiên hơn titleForHeaderInSection: Yêu cầu duy nhất là bạn đặt ước tínhSectionHeaderHeight trên chế độ xem bảng của bạn với một cái gì đó khác 0, nếu không thì viewForHeaderInSection: sẽ không bao giờ được gọi
romrom 17/2/2017

Thêm vào nhận xét của @ romrom: nếu bạn đã triển khai cả hai titleForHeaderInSection:viewForHeaderInSection:chế độ xem được trả về từ sau là một lớp con UITableViewHeaderFooterViewthì nó textLabel.textsẽ tự động được đặt thành phiên bản toàn titleForHeaderInSection:chuỗi của chuỗi. Để ngăn chặn hành vi này, không thực hiện titleForHeaderInSection:hoặc sử dụng nhãn tùy chỉnh thay vì kế thừa textLabel.
Ortwin Gentz

40

Bí quyết là hai phương thức đó thuộc về các UITableViewgiao thức khác nhau : tableView:titleForHeaderInSection:là một UITableViewDataSourcephương thức giao thức, tableView:viewForHeaderInSectionthuộc về UITableViewDelegate.

Điều đó có nghĩa là:

  • Nếu bạn thực hiện các phương thức nhưng chỉ gán cho mình như là dataSourcecho UITableView, tableView:viewForHeaderInSectionviệc thực hiện của bạn sẽ bị bỏ qua.

  • tableView:viewForHeaderInSectioncó mức độ ưu tiên cao hơn. Nếu bạn thực hiện cả hai phương pháp và gán cho mình là cả hai dataSourcedelegatecho UITableView, bạn sẽ trở lại quan điểm cho phần tiêu đề nhưng bạn tableView:titleForHeaderInSection:sẽ bị bỏ qua.

Tôi cũng đã thử loại bỏ tableView:heightForHeaderInSection:; nó hoạt động tốt và dường như không ảnh hưởng đến các thủ tục trên. Nhưng tài liệu nói rằng nó là cần thiết tableView:viewForHeaderInSectionđể hoạt động chính xác; Vì vậy, để an toàn, tốt nhất là thực hiện điều này.


6
Bạn đã làm cho ngày của tôi !!! Quên gán UITableViewDelegatecho self, bởi vì tôi nghĩ, đó tableView:viewForHeaderInSectionlà một UITableViewDataSourcephương pháp. Cảm ơn bạn!
denis631

1
"tableView: viewForHeaderInSection" không quan trọng. Điều quan trọng là bạn bằng cách nào đó trả lại một chiều cao. Bạn có thể đạt được điều đó thông qua 1. ước tính hoặc 2. giá trị được mã hóa cứng hoặc 3. a titleForHeadercó kích thước nội tại. Kích thước nội tại được tính toán dựa trên Họ phông chữ và kích thước.
Mật ong

28

@rmaddy đã khai sai nguyên tắc, hai lần: trong thực tế, tableView:viewForHeaderInSection:không không yêu cầu bạn cũng thực hiện tableView:heightForHeaderInSection:, và cũng có thể nó là hoàn toàn tốt đẹp để gọi cả titleForHeaderviewForHeader. Tôi sẽ nêu chính xác quy tắc chỉ cho hồ sơ:

Quy tắc đơn giản là viewForHeadersẽ không được gọi trừ khi bạn bằng cách nào đó cho chiều cao của tiêu đề. Bạn có thể làm điều này theo bất kỳ cách nào trong ba cách:

  • Thực hiện tableView:heightForHeaderInSection:.

  • Đặt bảng của sectionHeaderHeight.

  • Gọi titleForHeader(điều này bằng cách nào đó cung cấp cho tiêu đề một chiều cao mặc định nếu nó không có chiều cao khác).

Nếu bạn không làm những điều đó, bạn sẽ không có tiêu đề và viewForHeadersẽ không được gọi. Đó là bởi vì không có chiều cao, bộ thực thi sẽ không biết cách thay đổi kích thước khung nhìn, do đó, không cần phải hỏi một cái.


Từ các tài liệu cho tableView:viewForHeaderInSection:: "Phương pháp này chỉ hoạt động chính xác khi tableView:heightForHeaderInSection:cũng được thực hiện.".
rmaddy

1
Khỏe. Những gì các tài liệu nói, họ nói. Bây giờ thử nghiệm. Sự thật là như tôi đã nêu.
matt

Và làm thế nào bạn có thể có cả hai titleForHeaderInSectionviewForHeaderInSection? Chế độ xem bảng sẽ chỉ gọi một trong hai (tôi quên mất quyền ưu tiên tại thời điểm này).
rmaddy

1
Trên thực tế có một phần của câu đố, đó là đôi khi viewForHeader được gọi mà không có bất kỳ cách nào trong ba cách gán chiều cao đó. Tôi đã có điều này xảy ra, nơi tôi viewForHeaderđược gọi và tiêu đề xuất hiện tốt, cho đến một ngày, không có thay đổi về phía tôi, họ đã không làm . Đó là khi tôi bắt đầu thử nghiệm để khám phá những yêu cầu tối thiểu viewForHeaderđược gọi là gì. Và bây giờ tôi biết. Và bây giờ bạn cũng vậy.
matt

2
@texas Không, tôi không làm xamarin. Thêm một mức độ gián tiếp khác trên đầu khung Cacao sẽ khiến đầu tôi nổ tung. :)
matt

20

Đưa ra estimatedSectionHeaderHeightsectionHeaderHeightcác giá trị đã khắc phục vấn đề của tôi. ví dụ, self.tableView.estimatedSectionHeaderHeight = 100 self.tableView.sectionHeaderHeight = UITableViewAutomaticDimension


Vấn đề của tôi bắt đầu sau khi nâng cấp lên Swift 3.1. Giải pháp này đã sửa nó.
zevij

@pbuchheit Apple Docs cho biết nó có sẵn từ iOS 7.0+, vui lòng xem tại đây, developer.apple.com/documentation/uikit/uitableview/
Lỗi

@Sharukh Mastan Hình như bạn đúng. Vì một số lý do, tôi đã nhận được một cảnh báo khi tôi thử sử dụng tài sản đó, nhưng nó đã biến mất sau khi thực hiện một bản dựng sạch.
pbuchheit

7

Từ bỏ câu trả lời của rmaddy, tôi đã cố gắng ẩn chế độ xem Tiêu đề và đang trả về 0,0f cho "tableView: heightForHeaderInSection" và 0 height View from tableView:viewForHeaderInSection.

Sau khi thay đổi từ return 1.0fthành return 0.0ftrong tableView:heightForHeaderInSection, phương thức đại biểu tableView:viewForHeaderInSectionthực sự được gọi.

Hóa ra hiệu ứng mong muốn của tôi hoạt động mà không phải sử dụng "tableView: heightForHeaderInSection"; nhưng điều này có thể hữu ích cho những người khác đang gặp vấn đề khi nhận được phương thức ủy nhiệm "tableView: heightForHeaderInSection".


5

Bạn nên thực hiện tableView:heightForHeaderInSection:và đặt chiều cao cho tiêu đề> 0.

Phương thức ủy nhiệm này đi cùng với viewForHeaderInSection:phương thức.

Tôi hi vọng cái này giúp được.

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
         return 40;
}

Bạn đã kiểm tra rằng câu trả lời của bạn thực sự hoạt động? Vì bạn đọc kỹ nên sau đó tuyên bố rằng ban đầu viewForHeaderInSection được gọi. Nó không được gọi chỉ khi bảng được tải lại!
Karlis

5

Đáng lưu ý ngắn gọn rằng nếu bạn thực hiện tableView:heightForHeaderInSection:trả lại UITableViewAutomaticDimension, thì tableView:viewForHeaderInSection:sẽ không được gọi.

UITableViewAutomaticDimensiongiả định rằng một tiêu chuẩn UITableViewHeaderFooterViewsẽ được sử dụng được áp dụng với phương thức ủy nhiệm tableView:titleForHeaderInSection:.

Từ ý kiến ​​trong UITableView.h:

Trả lại giá trị này từ tableView:heightForHeaderInSection:hoặc tableView:heightForFooterInSection:dẫn đến chiều cao phù hợp với giá trị được trả về từ tableView:titleForHeaderInSection:hoặc tableView:titleForFooterInSection:nếu tiêu đề không bằng không.


1
nếu bạn đặt estimatedSectionHeaderHeightthành một giá trị nào đó, tableView:viewForHeaderInSectionsẽ được gọi (tương tự như cách kích thước tự động cho các hàng hoạt động)
GreatWiz

Thú vị, cảm ơn. Trở lại 7.1 , độ tinh tế của chiều cao ước tính này rất quan trọng đối với các ô , do đó, có thể cũng là trường hợp đối với các tiêu đề - nhưng bây giờ nó không liên quan lắm!
Stewohn 29/2/2016

3

Tôi vừa gặp sự cố với các tiêu đề không hiển thị cho iOS 7.1 , nhưng hoạt động tốt với các bản phát hành sau mà tôi đã thử nghiệm, rõ ràng với 8.1 và 8.4.

Đối với cùng một mã, 7.1 không gọi bất kỳ phương thức ủy nhiệm tiêu đề nào cả, bao gồm: tableView:heightForHeaderInSection:tableView:viewForHeaderInSection: .

Sau khi thử nghiệm, tôi thấy rằng việc xóa dòng này khỏi viewDidLoadcác tiêu đề đã tạo của tôi sẽ xuất hiện lại cho 7.1 và không ảnh hưởng đến các phiên bản khác mà tôi đã thử nghiệm:

// _Removing_ this line _fixed_ headers on 7.1
self.tableView.estimatedSectionHeaderHeight = 80;

Vì vậy, dường như có một số loại xung đột ở đó cho 7.1, ít nhất.


3

Vấn đề tương tự xảy ra với tôi nhưng khi tôi đang sử dụng tính toán chiều cao tự động từ xCode 9 , tôi không thể đưa ra bất kỳ giá trị chiều cao rõ ràng nào như đã đề cập ở trên. Sau một số thử nghiệm tôi đã có giải pháp , chúng ta phải ghi đè phương thức này như,

-(CGFloat)tableView:(UITableView *)tableView 
         estimatedHeightForHeaderInSection:(NSInteger)section
{
      return 44.0f;
}

Mặc dù tôi đã kiểm tra cả hai tùy chọn

  1. Tính toán chiều cao tự động
  2. Tính toán chiều cao ước tính tự động

từ bảng phân cảnh như apple nói, nhưng tôi vẫn gặp phải lỗi kỳ lạ này.

Xin lưu ý : Lỗi này chỉ được hiển thị trên phiên bản IOS-10 chứ không phải trên phiên bản iOS-11 . Có lẽ đó là một lỗi từ xCode. Cảm ơn


0

Đây là những gì tôi đã tìm thấy ( Swift 4 ) (nhờ nhận xét này về một câu hỏi khác)

Cho dù tôi đã sử dụng titleForHeaderInSection hay viewForHeaderInSection - không phải là họ không được gọi khi chế độ xem bảng được cuộn và các ô mới đang được tải, nhưng bất kỳ lựa chọn phông chữ nào tôi thực hiện cho textLabel của tiêu đề chỉ xuất hiện trên những gì ban đầu hiển thị khi tải , và không phải như bảng đã được cuộn.

Bản sửa lỗi là willDisplayHeaderView:

func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
    if let header = view as? UITableViewHeaderFooterView {
        header.textLabel?.font = UIFont(name: yourFont, size: 42)
    }
}

0

Trong trường hợp của tôi, tôi đã tạo chế độ xem tiêu đề bằng cách sử dụng UITableviewCellvà trả lại ô viewForHeaderInSectionnhư thế này

return cell

đã thay đổi điều này thành

return cell.contentView 

Đã làm cho tôi.


0

Trong trường hợp của tôi

viewForHeaderInSection

đã được thực hiện trong một lớp dẫn xuất ở xa mà không bận tâm đến việc chuyển thành siêu lớp.


0

Lý do tại sao viewForHeaderInSectionkhông được gọi là vì một trong hai lý do:

Hoặc bạn đã không thiết lập UITableViewDelegatehoặc bạn thiết lập UITableViewDelegatekhông chính xác.


0

Trong trường hợp của tôi, đó là lý do tôi đã không thực hiện:

func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat

-1

Đôi khi thiết lập tableview.delegatehoặc datasource = niltrong viewWillAppear:hoặc viewDidAppear:phương pháp có thể gây ra vấn đề này. Đảm bảo không làm điều này ...


-1

Tôi đã cắt và dán hai phương thức sau từ dự án Swift 2 vào dự án Swift 3 không bao giờ được gọi vì trong Swift 3, các phương thức này phải có "-" trước tên tham số đầu tiên.

func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return 44.0
}

func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {

    let headerView = tableView.dequeueReusableHeaderFooterView(withIdentifier: B2BTrolleyHeaderFooterView.reuseIdentifier) as! B2BTrolleyHeaderFooterView        
    return headerView
}
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.