Weak Reference (দুর্বল রেফারেন্স) হলো একটি অবজেক্টের রেফারেন্স যা ARC-তে তার রিটেন কাউন্ট বাড়ায় না। Apple Swift Language Guide, 2026 অনুযায়ী, weak রেফারেন্স weak কীওয়ার্ড দিয়ে ডিক্লেয়ার করা হয় এবং সবসময় অপশনাল হয়। যখন অবজেক্টটি ডিলোকেট হয়, তখন এর সমস্ত weak রেফারেন্স স্বয়ংক্রিয়ভাবে nil-এ সেট হয়ে যায়, যা ড্যাঙ্গলিং পয়েন্টার প্রতিরোধ করে এবং weak রেফারেন্সকে রিটেন সাইকেল ভাঙার জন্য একটি নিরাপদ ব্যবস্থা করে তোলে।
মূল বিষয়
weak কীওয়ার্ড; টাইপ সবসময় অপশনাল (?)Weak Reference হলো ARC (Automatic Reference Counting)-এ একটি অবজেক্টের অ-মালিকানাধীন রেফারেন্স। একটি শক্তিশালী রেফারেন্সের বিপরীতে, যা অবজেক্টের রিটেন কাউন্ট বাড়ায় এবং তার লাইফটাইম নিশ্চিত করে, একটি দুর্বল রেফারেন্স অবজেক্টটিকে ডিলোকেট হতে দেয় এমনকি যদি এটি এখনও রেফারেন্স করা হয়। ডিলোকেশনের পর, দুর্বল রেফারেন্স স্বয়ংক্রিয়ভাবে nil-এ সেট হয় — একে জিরোইং weak বলা হয়।
জিরোইং weak হলো Swift এবং Objective-C রানটাইমের একটি মূল বৈশিষ্ট্য। যখন একটি অবজেক্টের রেফারেন্স কাউন্ট শূন্যে পৌঁছায় এবং অবজেক্টটি ডিলোকেট হয়, রানটাইম এই অবজেক্টের সমস্ত weak রেফারেন্স (একটি বিশেষ weak টেবিলে সংরক্ষিত) এর মধ্য দিয়ে যায় এবং সেগুলোকে nil-এ সেট করে। এটি নিশ্চিত করে যে weak রেফারেন্সের মাধ্যমে মুক্ত মেমোরিতে অ্যাক্সেস (use-after-free) অসম্ভব — যেকোনো পড়া nil রিটার্ন করে।
Apple WWDC 2012 Session 406 অনুযায়ী, জিরোইং weak রেফারেন্স ড্যাঙ্গলিং পয়েন্টার সম্পর্কিত ক্র্যাশ বাগের একটি সম্পূর্ণ শ্রেণী দূর করেছে, যা ম্যানুয়াল মেমোরি ম্যানেজমেন্টে (MRR) সাধারণ ছিল। MRR-এ, weak রেফারেন্স শুধুমাত্র __unsafe_unretained হিসাবে বিদ্যমান ছিল — সেগুলো শূন্য হতো না, এবং ডিলোকেটেড অবজেক্টে অ্যাক্সেস EXC_BAD_ACCESS-এর কারণ হতো।
আসুন Apple ইকোসিস্টেমের উভয় ভাষায় weak রেফারেন্স ডিক্লেয়ার করার সিনট্যাক্স দেখি। শেয়ার্ড রানটাইম সত্ত্বেও, সিনট্যাক্স ভিন্ন, কিন্তু অর্থগতভাবে অভিন্ন।
Swift-এ, weak রেফারেন্স var-এর আগে weak কীওয়ার্ড দিয়ে ডিক্লেয়ার করা হয়। টাইপ সবসময় অপশনাল (Type?) হতে হবে, কারণ রেফারেন্স যেকোনো সময় nil হতে পারে। কনস্ট্যান্ট (let) weak হতে পারে না — শুধুমাত্র ভেরিয়েবল।
class ViewController: UIViewController {
// weak properties: only var, only optional
weak var delegate: ViewControllerDelegate?
weak var parentView: UIView?
weak var completionHandler: ((Bool) -> Void)? // ⚠️ ক্লোজার weak সংরক্ষণ করে না
// ⬆️ ত্রুটি: weak শুধুমাত্র class টাইপে প্রয়োগ করা যেতে পারে, closures-এ নয়
}
গুরুত্বপূর্ণ: weak শুধুমাত্র class ইনস্ট্যান্স (class টাইপ), AnyObject এবং AnyObject থেকে প্রাপ্ত প্রোটোকলের ক্ষেত্রে প্রযোজ্য। Struct, enum এবং ক্লোজার weak হতে পারে না — এগুলো ভ্যালু টাইপ এবং ARC-তে অংশগ্রহণ করে না।
Objective-C-এ, weak প্রপার্টি __weak অ্যাট্রিবিউট বা প্রপার্টি ডিক্লেয়ারেশনে weak মডিফায়ারের মাধ্যমে ডিক্লেয়ার করা হয়:
// Objective-C: weak property
@interface MyViewController : UIViewController
@property (weak, nonatomic) id<MyDelegate> delegate;
@end
// স্থানীয় weak ভেরিয়েবল
__weak MyObject *weakRef = someStrongObject;
Objective-C রানটাইমও জিরোইং weak প্রদান করে, তবে অতিরিক্তভাবে C স্ট্রাকচার এবং কিছু Core Foundation অবজেক্টের সাথে weak-এর ব্যবহার ব্লক করে। এগুলোর জন্য, __unsafe_unretained ব্যবহার করা হয় — জিরোইং ছাড়া।
দুর্বল রেফারেন্স একটি সার্বজনীন সমাধান নয়, বরং নির্দিষ্ট পরিস্থিতির জন্য একটি টুল। সর্বত্র weak ব্যবহার করলে অপ্রয়োজনীয় জটিলতা তৈরি হয় এবং পঠনযোগ্যতা নষ্ট হয়। আসুন সঠিক ব্যবহারের পরিস্থিতিগুলো দেখি।
ডেলিগেট — weak-এর জন্য প্রাথমিক পরিস্থিতি। মালিকানা অবজেক্ট (যেমন UITableView) নিজের একটি শক্তিশালী রেফারেন্স রাখে, যখন ডেলিগেটের (UIViewController) টেবিলের মালিক হওয়া উচিত নয়। Apple SDK গ্যারান্টি দেয় যে সমস্ত ডেলিগেট এবং dataSource weak। আপনার নিজের প্রোটোকলের জন্য, সর্বদা weak var delegate ব্যবহার করুন।
যখন একটি চাইল্ড অবজেক্টের তার প্যারেন্টকে রেফারেন্স করার প্রয়োজন হয় (যেমন ChildViewController কোঅর্ডিনেটরে অ্যাক্সেস), একটি weak রেফারেন্স ব্যবহার করুন। প্যারেন্ট চাইল্ডের মালিক (strong), চাইল্ড প্যারেন্টকে পর্যবেক্ষণ করে (weak) — রিটেন সাইকেল দূর হয়।
Capture list [weak self] — class প্রপার্টি হিসাবে সংরক্ষিত ক্লোজারে রিটেন সাইকেল এড়ানোর মানক উপায়। যদি self ক্লোজার সম্পূর্ণ হওয়ার আগে ডিলোকেট হতে পারে, তাহলে weak self বাধ্যতামূলক।
| পরিস্থিতি | Weak | Strong |
|---|---|---|
| ডেলিগেট | ✅ সবসময় weak | ❌ রিটেন সাইকেল |
| প্যারেন্ট → চাইল্ড | ❌ প্রয়োজন নেই (প্যারেন্টের মালিক হওয়া উচিত) | ✅ Strong |
| চাইল্ড → প্যারেন্ট | ✅ Weak | ❌ রিটেন সাইকেল |
| অ্যাসিন্ক কলব্যাক | ✅ [weak self] | ❌ রিটেন সাইকেল ঝুঁকি |
| শক্তিশালী যুগ্ম (owned) | ❌ unowned | ✅ Strong |
সাধারণ নিয়ম: যদি অবজেক্ট A, B-এর মালিক হয় (A → B strong), তাহলে B → A weak বা unowned হওয়া উচিত। শক্তিশালী রেফারেন্সের দিক সর্বদা মালিক থেকে অধস্তনের দিকে হওয়া উচিত।
weak এবং unowned উভয়ই রিটেন কাউন্ট বাড়ায় না, কিন্তু অবজেক্ট ডিলোকেশনের পরে আচরণে ভিন্ন। তাদের মধ্যে নির্বাচন লাইফটাইম গ্যারান্টি-র বিষয়।
Weak: স্বয়ংক্রিয়ভাবে nil হয়, টাইপ সবসময় অপশনাল, ব্যবহারের আগে আনর্যাপ প্রয়োজন। নিরাপদ — nil-এ অ্যাক্সেস ক্র্যাশের কারণ হয় না।
Unowned: nil হয় না, টাইপ নন-অপশনাল। যদি অবজেক্ট ডিলোকেট হয়, একটি unowned রেফারেন্স ড্যাঙ্গলিং পয়েন্টারে পরিণত হয় — এতে অ্যাক্সেস রানটাইম ক্র্যাশের কারণ হয়। Unowned ধরে নেয় যে অবজেক্টটি রেফারেন্সিং পক্ষের মতো কমপক্ষে ততদিন বেঁচে থাকে।
Weak বেছে নিন যদি: অবজেক্ট যেকোনো সময় ডিলোকেট হতে পারে (স্ক্রিন বন্ধ হওয়ার পর ডেলিগেট), আপনি অবজেক্টের লাইফটাইম নিয়ন্ত্রণ করেন না, বা গ্যারান্টি সম্পর্কে অনিশ্চিত। Weak হলো সার্বজনীন নিরাপদ পছন্দ।
Unowned বেছে নিন যদি: অবজেক্ট গ্যারান্টিযুক্ত যে রেফারেন্সিং অবজেক্টের আগে ডিলোকেট হবে না (যেমন Customer → CreditCard, যেখানে কার্ড গ্রাহক ছাড়া বিদ্যমান নেই)। Unowned আনর্যাপ ছাড়া একটি নন-অপশনাল API প্রদান করে, যা কোডে আরও সুবিধাজনক।
class Order {
let id: Int
var items: [Item] = []
init(id: Int) { self.id = id }
// শক্তিশালী সম্পর্ক: Order, Item-এর মালিক
func addItem(name: String) {
let item = Item(name: name, order: self)
items.append(item)
}
}
class Item {
let name: String
unowned let order: Order // ✅ unowned — Item, Order ছাড়া বাঁচে না
init(name: String, order: Order) {
self.name = name
self.order = order
}
}
// weak সহ উদাহরণ: লাইফটাইম গ্যারান্টি ছাড়া ডেলিগেট
protocol NetworkServiceDelegate: AnyObject {
func didReceiveResponse(data: Data)
}
class NetworkService {
weak var delegate: NetworkServiceDelegate? // ✅ weak — ডেলিগেট চলে যেতে পারে
}
উদাহরণে, Item unowned ব্যবহার করে কারণ একটি অর্ডার আইটেম অর্ডার ছাড়া থাকতে পারে না — লাইফটাইম গ্যারান্টি অটল। NetworkService weak ব্যবহার করে কারণ ডেলিগেট (যেমন ViewController) যেকোনো সময় বন্ধ এবং ডিলোকেট হতে পারে।
দুর্বল রেফারেন্স একটি শক্তিশালী টুল, কিন্তু iOS ডেভেলপমেন্টে সঠিক ব্যবহারের জন্য এদের সীমাবদ্ধতা বোঝা গুরুত্বপূর্ণ।
দুর্বল রেফারেন্স শক্তিশালীর চেয়ে ধীর: প্রতিটি অ্যাক্সেসে, রানটাইম পরীক্ষা করে যে অবজেক্টটি ডিলোকেট হয়েছে কিনা (weak টেবিলে lookup)। অধিকাংশ পরিস্থিতিতে, পার্থক্য অলক্ষিত, কিন্তু লক্ষ লক্ষ অ্যাক্সেস সহ হট লুপে, weak একটি বাধা হয়ে উঠতে পারে। উচ্চ-লোড পরিস্থিতির জন্য, strong ব্যবহার করুন এবং আর্কিটেকচার পুনর্বিন্যাস করুন।
Struct, enum, tuple — ভ্যালু টাইপ যা ARC-তে অংশগ্রহণ করে না। weak struct ডিক্লেয়ার করার প্রচেষ্টা কম্পাইলেশন ত্রুটির কারণ হয়। একটি ভ্যালু টাইপের দুর্বল রেফারেন্স সংরক্ষণের জন্য, class টাইপ বা ক্লোজারে একটি র্যাপার ব্যবহার করুন।
জিরোইং weak থ্রেড-নিরাপদ: যদি একটি থ্রেডে অবজেক্ট ডিলোকেট হয়, weak রেফারেন্স সব থ্রেডে পারমাণবিকভাবে শূন্য হয়। তবে, একটি weak রেফারেন্স পড়া এবং ডিরেফারেন্স করার মধ্যে ব্যবধান রেস কন্ডিশনের কারণ হতে পারে — weak রেফারেন্স প্রাপ্তি এবং ব্যবহারের মধ্যে অবজেক্ট ডিলোকেট হয়। সমাধান: একটি লোকাল ভেরিয়েবলে weak রেফারেন্সের strong ক্যাপচার।
// মাল্টিথ্রেডিং-এ weak সহ রেস কন্ডিশন
func performAsync() {
weak var weakSelf = self
queue.async {
// ⚠️ weakSelf চেক এবং ব্যবহারের মধ্যে nil হতে পারে
if weakSelf != nil {
weakSelf!.doSomething() // CRASH যদি nil হয়
}
}
}
// ✅ সমাধান: ব্যবহারের সময় strong ক্যাপচার
func performAsyncSafe() {
queue.async { [weak self] in
guard let strongSelf = self else { return }
strongSelf.doSomething() // strongSelf — স্থানীয় strong রেফারেন্স
}
}
নিরাপদ সংস্করণে, weak self ক্যাপচার করা হয়, তারপর অবিলম্বে একটি লোকাল strong ভেরিয়েবল strongSelf-এ আনর্যাপ করা হয়। যদি self এখনও জীবিত থাকে, এটি ব্লকের সময়কালের জন্য জীবিত থাকবে। যদি না থাকে, guard সক্রিয় হয় এবং কোড এক্সিকিউট হয় না। এই প্রয়োগরীতি হলো Swift-এ অ্যাসিনক্রোনাস ক্লোজারের জন্য মানক প্যাটার্ন।
IBOutlet Interface Builder-এ weak হওয়া উচিত কারণ ভিউ হায়ারার্কি ইতিমধ্যেই subview-এ একটি শক্তিশালী রেফারেন্স রাখে। কন্ট্রোলারে শক্তিশালী রেফারেন্সের নকল রিটেন সাইকেল তৈরি করে না কিন্তু অপ্রয়োজনীয়। আউটলেটে দুর্বল রেফারেন্স Apple-এর সুপারিশ, যদিও অনেক ডেভেলপার কোড সরলীকরণের জন্য strong ব্যবহার করে।
সচরাচর জিজ্ঞাসিত প্রশ্ন
না, weak শুধুমাত্র একটি বিদ্যমান অবজেক্ট বা nil-কে নির্দেশ করতে পারে। একটি নতুন অবজেক্ট তৈরি করার সময়, আপনি প্রথমে একটি শক্তিশালী রেফারেন্স পান (ইনিশিয়ালাইজারের মাধ্যমে), এবং শুধুমাত্র তারপর আপনি একটি দুর্বল রেফারেন্স নির্ধারণ করতে পারেন। শুরুতে weak nil একটি স্বাভাবিক অবস্থা।
Weak ARC-এর উপর ভিত্তি করে, যা শুধুমাত্র রেফারেন্স টাইপ (class) পরিচালনা করে। ভ্যালু টাইপ (struct, enum) অ্যাসাইনমেন্টে কপি হয় এবং এদের রিটেন কাউন্ট থাকে না। ভ্যালু টাইপের সাথে দুর্বল সম্পর্কের জন্য, class-এ weak প্রপার্টি সহ র্যাপার বা ক্লোজার ব্যবহার করুন।
একটি weak রেফারেন্সে প্রতিটি অ্যাক্সেস রানটাইম টেবিলে একটি lookup করে। লক্ষ লক্ষ পুনরাবৃত্তি সহ একটি লুপে, এটি একটি শক্তিশালী রেফারেন্সের চেয়ে 2–5 গুণ ধীর হতে পারে। হট পাথের জন্য, লুপের আগে weak-কে একটি লোকাল strong ভেরিয়েবলে কপি করুন।
যখন অবজেক্টের সমস্ত শক্তিশালী রেফারেন্স হারিয়ে যায় — স্কোপের শেষে, একটি প্রপার্টি পুনরায় নির্ধারণ করার সময়, বা স্ক্রিন বন্ধ হলে। একটি মাল্টিথ্রেডেড পরিবেশে, এটি কোডের দুটি লাইনের মধ্যে ঘটতে পারে। সর্বদা guard let বা if let-এর মাধ্যমে weak রেফারেন্স পরীক্ষা করুন।
অর্থগতভাবে অভিন্ন: উভয়ই জিরোইং weak প্রদান করে। পার্থক্য: Swift-এ অপশনাল টাইপ এবং var প্রয়োজন, Objective-C প্রপার্টি মডিফায়ার ব্যবহার করে। Objective-C __unsafe_unretained-ও সমর্থন করে — জিরোইং ছাড়া একটি দুর্বল রেফারেন্স (ড্যাঙ্গলিং পয়েন্টারের ঝুঁকি)।
সারসংক্ষেপ
weak var + অপশনাল টাইপ; শুধুমাত্র class টাইপ এবং AnyObject প্রোটোকলআমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন