หากต้องการทราบว่าเมื่อมุมมองตารางเสร็จสิ้นการโหลดเนื้อหาเราจำเป็นต้องมีความเข้าใจพื้นฐานเกี่ยวกับวิธีการใส่มุมมองบนหน้าจอ
ในวงจรชีวิตของแอพมีช่วงเวลาสำคัญ 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()สามารถสร้างปัญหาด้านประสิทธิภาพการทำงาน ฯลฯ แต่เมื่อรู้ว่าตัวเลือกเหล่านั้นคุณควรจะสามารถคิดได้ในอีกทางเลือกหนึ่งที่เหมาะสมกับความต้องการของคุณ