หากต้องการทราบว่าเมื่อมุมมองตารางเสร็จสิ้นการโหลดเนื้อหาเราจำเป็นต้องมีความเข้าใจพื้นฐานเกี่ยวกับวิธีการใส่มุมมองบนหน้าจอ
ในวงจรชีวิตของแอพมีช่วงเวลาสำคัญ 4 ช่วง:
- แอปได้รับกิจกรรม (สัมผัสตัวจับเวลาบล็อคที่ถูกส่ง ฯลฯ )
- แอพจัดการกับเหตุการณ์ (แก้ไขข้อ จำกัด เริ่มต้นเคลื่อนไหวเปลี่ยนพื้นหลัง ฯลฯ )
- แอปคำนวณลำดับชั้นมุมมองใหม่
- แอพแสดงลำดับชั้นมุมมองและแสดง
2 และ 3 ครั้งถูกแยกออกจากกันโดยสิ้นเชิง ทำไม สำหรับเหตุผลด้านประสิทธิภาพเราไม่ต้องการทำการคำนวณทั้งหมดในช่วงเวลา 3 ทุกครั้งที่มีการแก้ไข
ดังนั้นฉันคิดว่าคุณกำลังเผชิญกับกรณีเช่นนี้:
tableView.reloadData()
tableView.visibleCells.count // wrong count oO
เกิดอะไรขึ้นที่นี่?
เช่นเดียวกับมุมมองใด ๆ มุมมองตารางจะโหลดเนื้อหาใหม่อย่างเกียจคร้าน ที่จริงแล้วถ้าคุณโทรreloadData
หลายครั้งมันจะไม่สร้างปัญหาด้านประสิทธิภาพ มุมมองตารางจะคำนวณขนาดเนื้อหาใหม่โดยยึดตามการนำไปปฏิบัติของผู้ได้รับมอบหมายและรอสักครู่เพื่อโหลดเซลล์ เวลานี้เรียกว่าการผ่านเลย์เอาต์
โอเควิธีผ่านเลย์เอาต์
ในระหว่างการจัดวางผังแอพจะคำนวณเฟรมทั้งหมดของลำดับชั้นการดู การมีส่วนร่วม, คุณสามารถแทนที่วิธีการทุ่มเทlayoutSubviews
, updateLayoutConstraints
ฯลฯ ในUIView
และวิธีการที่เทียบเท่าใน subclass มุมมองควบคุม
นั่นคือสิ่งที่มุมมองของตารางทำ มันแทนที่layoutSubviews
และขึ้นอยู่กับการดำเนินงานของผู้ได้รับมอบหมายของคุณเพิ่มหรือลบเซลล์ มันโทรได้cellForRow
ทันทีก่อนที่จะเพิ่มและจัดโครงร่างเซลล์ใหม่willDisplay
ทันที หากคุณเรียกreloadData
หรือเพิ่มมุมมองตารางไปยังลำดับชั้นมุมมองตารางจะเพิ่มจำนวนเซลล์ตามที่จำเป็นเพื่อเติมเฟรมในช่วงเวลาที่สำคัญนี้
เอาล่ะ แต่ตอนนี้จะรู้ได้อย่างไรเมื่อมุมมองตารางเสร็จสิ้นการโหลดเนื้อหาใหม่
ตอนนี้เราสามารถเรียบเรียงคำถามใหม่อีกครั้ง: จะรู้ได้อย่างไรเมื่อมุมมองตารางเสร็จสิ้นการจัดวางหัวข้อย่อยแล้ว?
• วิธีที่ง่ายที่สุดคือเข้าไปในเลย์เอาต์ของมุมมองตาราง:
class MyTableView: UITableView {
func layoutSubviews() {
super.layoutSubviews()
// the displayed cells are loaded
}
}
โปรดทราบว่าวิธีนี้เรียกว่าหลายครั้งในวงจรชีวิตของมุมมองตาราง เนื่องจากการเลื่อนและลักษณะการทำงาน dequeue ของมุมมองตารางเซลล์จะถูกแก้ไขลบและเพิ่มบ่อยครั้ง แต่ใช้งานได้หลังจากsuper.layoutSubviews()
โหลดเซลล์แล้ว โซลูชันนี้เทียบเท่ากับรอwillDisplay
เหตุการณ์ของพา ธ ดัชนีล่าสุด เหตุการณ์นี้เรียกว่าในระหว่างการดำเนินการของlayoutSubviews
มุมมองตารางสำหรับแต่ละเซลล์ที่เพิ่ม
• อีกวิธีหนึ่งคือการได้รับการเรียกเมื่อแอปเสร็จสิ้นเลย์เอาต์
ตามที่อธิบายไว้ในเอกสารคุณสามารถใช้ตัวเลือกของUIView.animate(withDuration:completion)
:
tableView.reloadData()
UIView.animate(withDuration: 0) {
// layout done
}
โซลูชันนี้ใช้งานได้ แต่หน้าจอจะรีเฟรชหนึ่งครั้งระหว่างช่วงเวลาที่จัดวางและเวลาที่บล็อกถูกเรียก สิ่งนี้เทียบเท่ากับDispatchMain.async
โซลูชัน แต่ระบุไว้
• อีกทางเลือกหนึ่งฉันต้องการบังคับเค้าโครงของมุมมองตาราง
มีวิธีการเฉพาะเพื่อบังคับให้มุมมองใด ๆ ในการคำนวณทันทีเฟรมย่อยของมันlayoutIfNeeded
คือ:
tableView.reloadData()
table.layoutIfNeeded()
// layout done
อย่างไรก็ตามโปรดระวังการทำเช่นนี้จะลบการโหลดแบบสันหลังยาวที่ระบบใช้ การเรียกวิธีการเหล่านั้นซ้ำ ๆ อาจสร้างปัญหาประสิทธิภาพการทำงาน ตรวจสอบให้แน่ใจว่าจะไม่ถูกเรียกก่อนเฟรมของมุมมองตารางมิฉะนั้นมุมมองตารางจะถูกโหลดอีกครั้งและคุณจะไม่ได้รับแจ้ง
ฉันคิดว่าไม่มีวิธีแก้ปัญหาที่สมบูรณ์แบบ คลาส Subclassing อาจนำไปสู่ trubles เลย์เอาต์ผ่านเริ่มต้นจากด้านบนและไปด้านล่างดังนั้นจึงไม่ง่ายที่จะได้รับการแจ้งเตือนเมื่อเลย์เอาต์ทั้งหมดเสร็จสิ้น และlayoutIfNeeded()
สามารถสร้างปัญหาด้านประสิทธิภาพการทำงาน ฯลฯ แต่เมื่อรู้ว่าตัวเลือกเหล่านั้นคุณควรจะสามารถคิดได้ในอีกทางเลือกหนึ่งที่เหมาะสมกับความต้องการของคุณ