यह जानने के लिए कि जब तालिका दृश्य अपनी सामग्री लोड करना समाप्त करता है, तो हमें सबसे पहले इस बात की बुनियादी समझ होनी चाहिए कि विचारों को स्क्रीन पर कैसे रखा जाता है।
किसी ऐप के जीवन चक्र में 4 महत्वपूर्ण क्षण होते हैं:
- एप्लिकेशन को एक घटना (स्पर्श, टाइमर, ब्लॉक प्रेषण आदि) प्राप्त होती है
- एप्लिकेशन ईवेंट को संभालता है (यह एक बाधा को संशोधित करता है, एक एनीमेशन शुरू करता है, पृष्ठभूमि बदलता है आदि)
- एप्लिकेशन नए दृश्य पदानुक्रम की गणना करता है
- ऐप दृश्य पदानुक्रम को प्रस्तुत करता है और इसे प्रदर्शित करता है
2 और 3 बार पूरी तरह से अलग हो गए हैं। क्यों ? प्रदर्शन कारणों से, हम हर बार एक संशोधन किए जाने के बाद हर पल 3 की गणना करना नहीं चाहते हैं।
इसलिए, मुझे लगता है कि आप इस तरह के एक मामले का सामना कर रहे हैं:
tableView.reloadData()
tableView.visibleCells.count // wrong count oO
यहाँ क्या गलत है?
किसी भी दृश्य की तरह, एक टेबल दृश्य अपनी सामग्री को आलसी तरीके से पुनः लोड करता है। दरअसल, यदि आप reloadDataकई बार कॉल करते हैं तो यह प्रदर्शन समस्याओं को पैदा नहीं करेगा। तालिका दृश्य अपने प्रतिनिधि कार्यान्वयन के आधार पर केवल इसकी सामग्री के आकार को फिर से प्रदर्शित करता है और इसकी कोशिकाओं को लोड करने के लिए पल 3 की प्रतीक्षा करता है। इस समय को लेआउट पास कहा जाता है।
ठीक है, लेआउट पास में कैसे जाएं?
लेआउट पास के दौरान, ऐप दृश्य पदानुक्रम के सभी फ़्रेमों की गणना करता है। शामिल हो के लिए, आपको समर्पित तरीकों ओवरराइड कर सकते हैं layoutSubviews, updateLayoutConstraintsआदि एक में UIViewऔर एक दृश्य नियंत्रक उपवर्ग में बराबर तरीकों।
ठीक वैसा ही एक टेबल व्यू करता है। यह ओवरराइड करता है layoutSubviewsऔर आपके प्रतिनिधि कार्यान्वयन के आधार पर कोशिकाओं को जोड़ता या हटाता है। यह cellForRowनए सेल को जोड़ने और बिछाने से ठीक पहले कॉल करता है, willDisplayठीक उसके बाद। यदि आपने reloadDataपदानुक्रम में तालिका दृश्य को कॉल किया या जोड़ा है, तो इस महत्वपूर्ण क्षण में इसके फ़्रेम को भरने के लिए तालिकाओं के दृश्य में उतनी कोशिकाएँ शामिल हैं जितनी आवश्यक हैं।
ठीक है, लेकिन अब, कैसे पता चलेगा जब एक टेबल व्यू ने अपनी सामग्री को फिर से लोड करना समाप्त कर दिया है?
अब हम इस सवाल को फिर से उठा सकते हैं: कैसे पता करें कि जब एक टेबल व्यू ने अपने सबव्यू को खत्म कर दिया है?
• टेबल व्यू के लेआउट में आने का सबसे आसान तरीका है:
class MyTableView: UITableView {
func layoutSubviews() {
super.layoutSubviews()
// the displayed cells are loaded
}
}
ध्यान दें कि तालिका दृश्य के जीवन चक्र में इस विधि को कई बार कहा जाता है। स्क्रॉल और तालिका दृश्य के विचलन व्यवहार के कारण, कोशिकाओं को संशोधित, हटा दिया जाता है और अक्सर जोड़ा जाता है। लेकिन यह काम करता है, ठीक इसके बाद 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
हालांकि सावधान रहें, ऐसा करने से सिस्टम द्वारा उपयोग किए जाने वाले आलसी लोडिंग को हटा दिया जाएगा। उन तरीकों को बार-बार कॉल करने से प्रदर्शन समस्याएं पैदा हो सकती हैं। सुनिश्चित करें कि टेबल व्यू के फ्रेम की गणना होने से पहले उन्हें कॉल नहीं किया जाएगा, अन्यथा टेबल व्यू फिर से लोड हो जाएगा और आपको सूचित नहीं किया जाएगा।
मुझे लगता है कि कोई सही समाधान नहीं है। सबक्लासिंग कक्षाएं ट्रबल को जन्म दे सकती हैं। एक लेआउट पास ऊपर से शुरू होता है और नीचे तक जाता है इसलिए यह सूचित करना आसान नहीं है कि सभी लेआउट कब किए जाते हैं। और layoutIfNeeded()प्रदर्शन के मुद्दे आदि बना सकते हैं, लेकिन उन विकल्पों को जानते हुए, आपको एक विकल्प पर सोचने में सक्षम होना चाहिए जो आपकी आवश्यकता के अनुकूल होगा।