UITableView: viewForHeaderInSection: ไม่ถูกเรียกระหว่างการโหลดข้อมูลซ้ำ:


127

ฉันได้ตั้งค่า tableview ที่ถูกต้องกับผู้ร่วมประชุมและแหล่งข้อมูลความเชื่อมโยง .. วิธี reloadData viewForHeaderInSection:เรียกแหล่งข้อมูลและวิธีการผู้รับมอบสิทธิ์ยกเว้น

เหตุผลที่เป็นเช่นนั้น?


30
คือheightForHeaderInSection:การดำเนินการ?
07:00 น

คุณได้ตั้งค่าสำหรับ TableView แล้วsectionHeaderHeightหรือยัง?
Carter Medlin

คำตอบ:


256

การใช้ต้องให้คุณยังดำเนินการtableView:viewForHeaderInSection: tableView:heightForHeaderInSection:สิ่งนี้ควรส่งคืนความสูงที่ไม่ใช่ศูนย์ที่เหมาะสมสำหรับส่วนหัว ตรวจสอบให้แน่ใจว่าคุณไม่ได้ใช้ไฟล์tableView:titleForHeaderInSection:. คุณควรใช้เพียงอย่างใดอย่างหนึ่ง ( viewForHeaderหรือtitleForHeader)


3
ตรวจสอบว่าไม่มีการพิมพ์ผิดในลายเซ็นของวิธีการ อักษรผิดหนึ่งตัวหมายความว่าจะไม่ถูกเรียก ตรวจสอบกรณีด้วย numberOfSectionsนอกจากนี้ยังให้แน่ใจว่าคุณจะกลับมาจาก 0
rmaddy

ทุกอย่างถูกต้องและรวบรวมได้อย่างถูกต้อง .. ปัญหาที่ฉันต้องการทำความเข้าใจคือช่วงเวลาที่เมธอดเรียกว่า .. tableView: viewForHeaderInSection ถูกเรียกเมื่อตารางกำลังจะแสดงและไม่ได้เป็นส่วนหนึ่งของการดำเนินการซิงค์ของ [ tableview reloadData]
inforeqd

@maddy OMG ขอบคุณฉันมันโง่มากที่ฉันสร้างอินสแตนซ์ของฉัน แต่ฉันไม่ได้ต่อท้ายอาร์เรย์ของฉัน
Happiehappie

4
คุณสามารถมีได้ทั้งสองอย่าง viewForHeaderInSection: จะมีลำดับความสำคัญเหนือ titleForHeaderInSection: ข้อกำหนดเดียวคือคุณตั้งค่าประมาณ SectionHeaderHeight บนมุมมองตารางของคุณด้วยสิ่งที่แตกต่างจาก 0 มิฉะนั้น viewForHeaderInSection: จะไม่ถูกเรียก
romrom

การเพิ่มความคิดเห็นของ @ romrom: หากคุณใช้ทั้งสองอย่าง titleForHeaderInSection:และviewForHeaderInSection:และมุมมองที่ส่งกลับจากหลังเป็นคลาสย่อยจากUITableViewHeaderFooterViewนั้นมันtextLabel.textจะถูกตั้งค่าเป็นtitleForHeaderInSection:สตริงทั้งหมดโดยอัตโนมัติ เพื่อป้องกันไม่ให้ปัญหานี้อย่างใดอย่างหนึ่งไม่ได้ใช้หรือใช้ฉลากที่กำหนดเองแทนการรับมรดกtitleForHeaderInSection: textLabel
Ortwin Gentz

40

เคล็ดลับคือว่าทั้งสองวิธีการที่แตกต่างกันเป็นUITableViewโปรโตคอล: tableView:titleForHeaderInSection:เป็นUITableViewDataSourceวิธีการโปรโตคอลที่เป็นtableView:viewForHeaderInSectionUITableViewDelegate

นั่นหมายความว่า:

  • หากคุณใช้วิธีการ แต่กำหนดตัวเองเป็น dataSourceสำหรับวิธีการUITableViewเท่านั้นtableView:viewForHeaderInSectionการใช้งานของคุณ จะถูกละเว้น

  • tableView:viewForHeaderInSectionมีลำดับความสำคัญสูงกว่า หากคุณใช้ทั้งสองวิธีและกำหนดตัวเองเป็นทั้งสอง dataSourceและdelegateสำหรับวิธีUITableViewนี้คุณจะส่งคืนมุมมองสำหรับส่วนหัวของส่วน แต่คุณ tableView:titleForHeaderInSection:จะถูกเพิกเฉย

ฉันได้ลองลบtableView:heightForHeaderInSection:แล้วด้วย มันใช้งานได้ดีและดูเหมือนจะไม่มีผลกับขั้นตอนข้างต้น แต่เอกสารระบุว่าจำเป็นสำหรับการtableView:viewForHeaderInSectionทำงานอย่างถูกต้อง ดังนั้นเพื่อความปลอดภัยจึงควรใช้สิ่งนี้เช่นกัน


6
คุณทำให้วันของฉัน !!! ลืมกำหนดUITableViewDelegateให้selfเพราะคิดว่าtableView:viewForHeaderInSectionเป็นUITableViewDataSourceวิธีการ ขอบคุณ!
denis631

1
"tableView: viewForHeaderInSection" ไม่มีความสำคัญ สิ่งที่สำคัญก็คือคุณอย่างใดกลับสูง คุณสามารถทำได้โดยใช้ 1. ค่าประมาณหรือ 2. ค่าที่เข้ารหัสหรือ 3. a titleForHeaderซึ่งมีขนาดที่แท้จริง ขนาดที่แท้จริงคำนวณตามตระกูลฟอนต์และขนาด
น้ำผึ้ง

28

@rmaddy ได้ misstated กฎครั้งที่สอง: ในความเป็นจริงtableView:viewForHeaderInSection:ไม่ได้ต้องการให้คุณยังดำเนินการtableView:heightForHeaderInSection:และยังเป็นดีอย่างสมบูรณ์แบบที่จะเรียกทั้งสองและtitleForHeader viewForHeaderฉันจะระบุกฎอย่างถูกต้องสำหรับบันทึก:

กฎเป็นเพียงที่viewForHeaderจะไม่ถูกเรียกเว้นแต่คุณจะให้ส่วนหัวมีความสูง คุณสามารถทำได้สามวิธีรวมกัน:

  • tableView:heightForHeaderInSection:Implement

  • sectionHeaderHeightการตั้งค่าของตาราง

  • โทรtitleForHeader(สิ่งนี้จะทำให้ส่วนหัวมีความสูงเริ่มต้นหากไม่มี)

หากคุณไม่ทำสิ่งเหล่านั้นคุณจะไม่มีส่วนหัวและviewForHeaderจะไม่ถูกเรียก นั่นเป็นเพราะหากไม่มีความสูงรันไทม์จะไม่ทราบวิธีปรับขนาดมุมมองดังนั้นจึงไม่ต้องขออย่างใดอย่างหนึ่ง


จากเอกสารสำหรับtableView:viewForHeaderInSection:: "วิธีนี้ใช้ได้ผลtableView:heightForHeaderInSection:ก็ต่อเมื่อมีการนำไปใช้ด้วย"
rmaddy

1
ละเอียด. สิ่งที่เอกสารพูดพวกเขาพูด ตอนนี้ทดลอง ข้อเท็จจริงเป็นไปตามที่ผมแจ้งไว้
แม

และคุณจะมีทั้งสองtitleForHeaderInSectionและได้viewForHeaderInSectionอย่างไร? มุมมองตารางจะเรียกหนึ่งในสองเท่านั้น (ฉันลืมว่าสิ่งใดมีความสำคัญในขณะนี้)
rmaddy

1
จริงๆแล้วมีจิ๊กซอว์อีกชิ้นหนึ่งซึ่งบางครั้ง viewForHeaderถูกเรียกโดยไม่ต้องกำหนดความสูงสามวิธี ฉันมีเรื่องนี้เกิดขึ้นที่ฉันviewForHeaderถูกเรียกตัวและส่วนหัวปรากฏตัวขึ้นได้ดีจนกระทั่งวันหนึ่งมีการเปลี่ยนแปลงในส่วนของฉันไม่มีพวกเขาไม่ได้ นั่นคือตอนที่ฉันเริ่มทดลองเพื่อค้นหาความต้องการขั้นต่ำviewForHeaderที่เรียกว่าอะไร และตอนนี้ฉันรู้แล้ว และตอนนี้คุณก็เช่นกัน
แม

2
@texas ไม่ฉันไม่ทำ xamarin การเพิ่มทิศทางอีกระดับที่ด้านบนของกรอบ Cocoa จะทำให้หัวของฉันระเบิด :)
แมตต์

20

การให้estimatedSectionHeaderHeightและsectionHeaderHeightค่าต่างๆช่วยแก้ปัญหาของฉันได้ เช่น, self.tableView.estimatedSectionHeaderHeight = 100 self.tableView.sectionHeaderHeight = UITableViewAutomaticDimension


ปัญหาของฉันเริ่มต้นหลังจากอัปเกรดเป็น Swift 3.1 วิธีนี้แก้ไขได้
zevij

@pbuchheit Apple Docs บอกว่าพร้อมใช้งานจาก iOS 7.0+ โปรดดูที่นี่developer.apple.com/documentation/uikit/uitableview/…
Sharukh Mastan

@Sharukh Mastan ดูเหมือนว่าคุณจะถูกต้อง ด้วยเหตุผลบางอย่างฉันได้รับคำเตือนเมื่อพยายามใช้คุณสมบัตินั้น แต่มันก็หายไปหลังจากทำการสร้างใหม่ทั้งหมด
pbuchheit

7

จะปิด rmaddy คำตอบของผมก็พยายามที่จะซ่อนมุมมองส่วนหัวและกำลังจะกลับ 0.0f สำหรับ 'tableView: heightForHeaderInSection' และ 0 tableView:viewForHeaderInSectionสูงมุมมองจาก

หลังจากเปลี่ยนจากreturn 1.0fเป็นreturn 0.0fในtableView:heightForHeaderInSectionวิธีการมอบหมายtableView:viewForHeaderInSectionได้ถูกเรียกอย่างแท้จริง

ปรากฎว่าเอฟเฟกต์ที่ฉันต้องการใช้งานได้โดยไม่ต้องใช้ "tableView: heightForHeaderInSection"; แต่อาจเป็นประโยชน์สำหรับผู้อื่นที่มีปัญหาในการเรียกเมธอดผู้แทน "tableView: heightForHeaderInSection"


5

คุณควรใช้tableView:heightForHeaderInSection:และตั้งค่าความสูงสำหรับส่วนหัว> 0

วิธีการมอบหมายนี้ไปพร้อมกับviewForHeaderInSection:วิธีการ

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

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

คุณทดสอบแล้วว่าคำตอบของคุณใช้งานได้จริงหรือไม่? ถ้าคุณอ่านอย่างละเอียดแล้วจะมีการระบุว่าในตอนแรกเรียกว่า viewForHeaderInSection ไม่ได้เรียกเฉพาะเมื่อตารางถูกโหลดใหม่!
Karlis

5

เป็นที่น่าสังเกตสั้น ๆ ว่าหากคุณดำเนินการตามtableView:heightForHeaderInSection:ผลตอบแทนUITableViewAutomaticDimensionแล้วtableView:viewForHeaderInSection:จะไม่ถูกเรียก

UITableViewAutomaticDimensionสันนิษฐานว่าเป็นมาตรฐานที่จะใช้ว่าเป็นประชากรที่มีวิธีการมอบหมายUITableViewHeaderFooterViewtableView:titleForHeaderInSection:

จากความคิดเห็นในUITableView.h:

การส่งคืนค่านี้จากtableView:heightForHeaderInSection:หรือtableView:heightForFooterInSection:ผลลัพธ์เป็นความสูงที่พอดีกับค่าที่ส่งกลับจากtableView:titleForHeaderInSection:หรือtableView:titleForFooterInSection:ถ้าชื่อเรื่องไม่ใช่ศูนย์


1
หากคุณตั้งค่าestimatedSectionHeaderHeightเป็นค่าบางค่าtableView:viewForHeaderInSectionจะถูกเรียก (คล้ายกับการทำงานของขนาดอัตโนมัติสำหรับแถว)
GreatWiz

น่าสนใจขอบคุณ ย้อนกลับไปที่ 7.1 ความละเอียดอ่อนของความสูงโดยประมาณนี้มีความสำคัญต่อเซลล์ดังนั้นอาจเป็นกรณีของส่วนหัวด้วยเช่นกัน - แต่ตอนนี้มันไม่เกี่ยวข้องมากนัก!
Benjohn

3

ฉันเพิ่งมีปัญหากับส่วนหัวที่ไม่แสดงสำหรับiOS 7.1แต่ทำงานได้ดีกับรุ่นที่ใหม่กว่าที่ฉันได้ทดสอบอย่างชัดเจนกับ 8.1 และ 8.4

สำหรับรหัสเดียวกัน 7.1 ไม่ได้เรียกใช้เมธอดการมอบหมายส่วนหัวส่วนใดเลยรวมถึง: tableView:heightForHeaderInSection:และtableView:viewForHeaderInSection:.

หลังจากการทดลองฉันพบว่าการลบบรรทัดนี้ออกจากviewDidLoadส่วนหัวที่สร้างขึ้นของฉันปรากฏขึ้นอีกครั้งสำหรับ 7.1 และไม่ส่งผลกระทบต่อเวอร์ชันอื่นที่ฉันทดสอบ:

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

…ดังนั้นดูเหมือนว่าจะมีข้อขัดแย้งบางอย่างสำหรับ 7.1 เป็นอย่างน้อย


3

เกิดปัญหาเดียวกันกับฉัน แต่เนื่องจากฉันใช้การคำนวณความสูงอัตโนมัติจากxCode 9ฉันจึงไม่สามารถให้ค่าความสูงที่ชัดเจนตามที่กล่าวไว้ข้างต้นได้ หลังจากการทดลองบางอย่างฉันได้วิธีแก้ปัญหาเราต้องแทนที่วิธีนี้เป็น

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

แม้ว่าฉันได้ตรวจสอบทั้งสองตัวเลือกแล้ว

  1. การคำนวณความสูงอัตโนมัติ
  2. การคำนวณความสูงโดยประมาณอัตโนมัติ

จากสตอรี่บอร์ดตามที่ Apple บอก แต่ฉันก็ยังพบข้อผิดพลาดแปลก ๆ นี้

หมายเหตุ : ข้อผิดพลาดนี้ก็แสดงให้เห็นเฉพาะในIOS-10รุ่นที่ไม่ได้อยู่บนIOS-11รุ่น อาจจะเป็นบั๊กจาก xCode ขอบคุณ


0

นี่คือสิ่งที่ฉันพบ ( Swift 4 ) (ขอบคุณความคิดเห็นนี้สำหรับคำถามอื่น)

ไม่ว่าฉันจะใช้ titleForHeaderInSection หรือ viewForHeaderInSection - ไม่ใช่ว่าพวกเขาไม่ได้รับการเรียกใช้เมื่อมีการเลื่อน tableview และเซลล์ใหม่กำลังโหลด แต่ตัวเลือกแบบอักษรใด ๆ ที่ฉันทำสำหรับ textLabel ของ headerView จะปรากฏเฉพาะในสิ่งที่มองเห็นได้ในตอนแรกเมื่อโหลดเท่านั้น และไม่ใช่ตามที่ตารางถูกเลื่อน

การแก้ไขคือ 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

ในกรณีของฉันฉันได้สร้างมุมมองส่วนหัวโดยใช้UITableviewCellและส่งคืนเซลล์ในviewForHeaderInSectionลักษณะนี้

return cell

เปลี่ยนสิ่งนี้เป็น

return cell.contentView 

ทำงานให้ฉัน


0

ในกรณีของฉัน

viewForHeaderInSection

ถูกนำไปใช้ในคลาสที่ได้รับมาซึ่งอยู่ห่างไกลออกไปซึ่งไม่รบกวนเดซี่เข้าสู่ซูเปอร์คลาส


0

สาเหตุที่viewForHeaderInSectionไม่ถูกเรียกนั้นมาจากหนึ่งในสองเหตุผล:

คุณไม่ได้ตั้งค่าของคุณUITableViewDelegateหรือคุณตั้งค่าUITableViewDelegateไม่ถูกต้อง


0

ในกรณีของฉันมันเป็นสาเหตุที่ฉันไม่ได้ใช้:

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

-1

บางครั้งการตั้งค่าtableview.delegateหรือdatasource = nilในviewWillAppear:หรือviewDidAppear:วิธีการอาจทำให้เกิดปัญหานี้ อย่าทำแบบนี้ ...


-1

ฉันได้ตัดและวางสองวิธีต่อไปนี้จากโปรเจ็กต์ Swift 2 ลงในโปรเจ็กต์ Swift 3 ของฉันซึ่งไม่เคยถูกเรียกเพราะใน Swift 3 วิธีการเหล่านี้ต้องมี "-" ก่อนชื่อพารามิเตอร์ตัวแรก

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