weak self ব্যবহার করা হয় মেমোরি ম্যানেজমেন্টের জন্য। একটি অবজেক্ট অন্য অবজেক্টের রেফারেন্স ধরে রাখলে প্যারেন্ট অবজেক্ট ডিএলোকেট বা মেমোরি থেকে মুছে গেলে যাতে চাইল্ড অবজেক্টেও মুছে যায় কিংবা চাইল্ড অবজেক্টের জন্য মেমোরি দখল করে না রাখে সে জন্য weak self ব্যবহার করা হয়। এক্ষেত্রে self অপশনাল হয়ে যায় তাই self রেফারেন্সে নাল চেক কিংবা ? চিহ্ন ব্যবহার করতে হবে।
ক্লোজারের ক্ষেত্রে weak self এর ব্যবহার বেশি হয়ে থাকে। এছাড়াও ডেলিগেট ব্যবহারের ক্ষেত্রেেও এর ব্যবহার রয়েছে।
এলার্ট ডায়লগের ক্লোজারে ব্যবহার:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let alert = UIAlertController(title: "My Title",
message: "Hello this is a message",
preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Done",
style: .cancel,
handler: { [weak self] _ in
// Null check as self can be null here as we use weak self
guard let mSelf = self else { return }
// as myFunction() calls from ViewController object which is self, if not use [weak self] it will
// keep a strong reference with ViewController and will not destroy after dismiss UIAlertController
mSelf.myFunction()
}))
} // viewDidLoad
private func myFunction() {
}
}
উপরের কোডে দেখতে পাচ্ছি একটি এলার্ট ডায়লগ viewDidLoad() এর ভিতর রয়েছে। এলার্ট ডায়লগ যখন ডিসমিস হবে তখন myFunction() কল হবে। myFunction() রয়েছে ViewController এর ভিতর যা এলার্ট ডায়লগের ভিতরে self দিয়ে কল করা হয়।
যখন এলার্ট ডায়লগ ডিসমিস করা হবে তখন self এর জন্য যাতে মেমোরি থেকে এলার্ট ডায়লগ অবজেক্ট মুছে বা ডিএলোকেট হয়ে যেতে বাধাগ্রস্থ না হয় সে জন্য weak self ব্যবহার করা হয়েছে। এখন এলার্ট ডায়লগ ডিসমিস হলে এলার্ট অবজেক্ট মেমোরি থেকে মুছে যাবে।
এবার নিজের তৈরি ক্লোজারে weak self এর ব্যবহার দেখি:
import UIKit
class ViewController: UIViewController {
private var data: Data?
override func viewDidLoad() {
super.viewDidLoad()
getData(string: "") { [weak self] (data) in
self?.data = data
}
} // viewDidLoad
private func getData(string: String, completion: ((Data?) -> Void)) {
completion(nil)
}
}
হয়তো ইন্টারনেট এপিআই কল কিংবা বড় অপারেশন চালিয়ে ক্লোজার ব্যবহার করে তার রেজাল্ট পেতে চাচ্ছেন। তখন যদি এরকম ক্লোজারে self ব্যবহারের প্রয়োজন হয় তবে weak self ব্যবহার করলে ক্লোজারের কাজ শেষ হলে মেমোরি থেকে মুছে যাবে এতে মেমোরি খালি হয়ে এ্যাপের পারফরমেন্স কমিয়ে দিবে না।
ডেলিগেটের ক্ষেত্রে weak এর ব্যবহার দেখি:
import UIKit
protocol MyViewControllerDelegate: AnyObject {
func myAction()
}
class ViewController: UIViewController {
weak var delegate: MyViewControllerDelegate?
override func viewDidLoad() {
super.viewDidLoad()
} // viewDidLoad
} // ViewController
// Another ViewController or class
class AnotherVC: UIViewController, MyViewControllerDelegate {
private let vc = ViewController()
override func viewDidLoad() {
super.viewDidLoad()
// If this class destroy then MyViewControllerDelegate will destroy too if use weak
vc.delegate = self
} // viewDidLoad
func myAction() {
//
}
}
এখানে ডেলিগেটের রেফারেন্সে এ্যাসাইন করা হয়েছে self এক্ষেত্রে weak ভেরিয়েবল হিসেবে ডেলিগেট অবজেক্ট নেয়া হয়েছে।
যখন আমরা বড় কোন প্রজেক্ট করবো তখন এইরকম ভাবে মেমোরি ম্যানেজমেন্ট করা উচিত এতে এ্যাপের পারফরমেন্স ঠিক থাকবে। ছোট প্রজেক্টের ক্ষেত্রে তেমন কোন সমস্যা নেই তবে বিষয়টাতে অভ্যস্ত থাকার জন্য হলেও এইধরণের বিষয়গুলো অনুসরন করা উচিত যাতে বড় প্রজেক্ট করার সময় ভুলে না যাই।