যখন কোনও সারণী দর্শন তার সামগ্রীটি লোড করা শেষ করে, তখন আমাদের প্রথমে ভিউগুলি কীভাবে স্ক্রিনে রাখা হয় তার একটি প্রাথমিক ধারণা থাকা দরকার।
একটি অ্যাপ্লিকেশনটির জীবন চক্রের মধ্যে 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সমাধানের সমতুল্য তবে নির্দিষ্ট করা আছে।
Ternative বিকল্পভাবে, আমি টেবিল দৃশ্যের লেআউটটি জোর করে পছন্দ করতে চাই
যে কোনও ভিউকে তত্ক্ষণাত্ এর সাবভিউ ফ্রেমগুলি গণনা করতে বাধ্য করার জন্য একটি উত্সর্গীকৃত পদ্ধতি রয়েছে layoutIfNeeded:
tableView.reloadData()
table.layoutIfNeeded()
// layout done
তবে সাবধান থাকুন, এটি করার ফলে সিস্টেমের দ্বারা ব্যবহৃত অলস লোডিং দূর হবে। এই পদ্ধতিগুলিকে বারবার কল করা পারফরম্যান্সের সমস্যা তৈরি করতে পারে। সারণী দর্শনটির ফ্রেম গণনা করার আগে তাদের ডাকা হবে না তা নিশ্চিত করুন, অন্যথায় সারণী দর্শনটি আবার লোড হবে এবং আপনাকে অবহিত করা হবে না।
আমি মনে করি এর কোনও নিখুঁত সমাধান নেই। সাবক্লাসিং ক্লাসগুলি অসুবিধা হতে পারে। একটি লেআউট পাস উপরে থেকে শুরু হয় এবং নীচে যায় যাতে সমস্ত লেআউট সম্পন্ন হওয়ার পরে এটি অবহিত হওয়া সহজ নয়। এবং layoutIfNeeded()পারফরম্যান্স সম্পর্কিত সমস্যাগুলি তৈরি করতে পারে ইত্যাদি But কিন্তু এই বিকল্পগুলি জেনে আপনি আপনার প্রয়োজনের সাথে খাপ খায় এমন কোনও বিকল্পে ভাবতে সক্ষম হবেন।