defer Swift-এ একটি নিয়ন্ত্রণ প্রবাহ নির্মাণ যা বর্তমান সুযোগ (scope) থেকে বেরিয়ে যাওয়ার সময় কোডের একটি ব্লকের কার্যকর করার সময়সূচী করে। defer ব্লক সুযোগ কীভাবে শেষ হয় তা নির্বিশেষে কার্যকর হয় — return, break, throw, fatalError বা সাধারণ সমাপ্তি। Swift Language Guide (2025) অনুসারে, যখন একই সুযোগে একাধিক defer উপস্থিত থাকে, তখন সেগুলি ঘোষণার বিপরীত ক্রমে কার্যকর হয় — শেষ ঘোষিত defer প্রথমে চলে (LIFO)। এটি defer-কে সম্পদের নিশ্চিত পরিষ্কারের জন্য অপরিহার্য করে তোলে: ফাইল ডিস্ক্রিপ্টর বন্ধ করা, লক মুক্ত করা, অস্থায়ী পয়েন্টার মুক্ত করা, তাড়াতাড়ি বেরিয়ে যাওয়ার সময় পরিষ্কার মিস করার ঝুঁকি ছাড়াই।
মূল পয়েন্ট
defer Swift-এ একটি নিয়ন্ত্রণ প্রবাহ নির্মাণ, যা Swift 2.0 (2015)-এ প্রবর্তিত হয়েছে, যা তার ব্লকের কার্যকর করা স্থগিত করে যতক্ষণ না বর্তমান সুযোগ শেষ হয়। মূল বৈশিষ্ট্য: defer গ্যারান্টি দেয় যে তার বডি সুযোগ কীভাবে শেষ হয় তা নির্বিশেষে কার্যকর হবে — সফলভাবে (return), ত্রুটি সহ (throw), অকালে (break, continue), বা মারাত্মকভাবে (fatalError, precondition)।
সিনট্যাক্টিকভাবে, defer defer { /* কোড */ } এর মতো দেখায় এবং সুযোগের ভিতরে যে কোনো জায়গায় রাখা যেতে পারে। Swift কম্পাইলার গ্যারান্টি দেয় যে defer-এর ভিতরের কোড কার্যকর হবে এমনকি যদি defer ঘোষণা এবং সুযোগের শেষের মধ্যে কোনো ব্যতিক্রম বা return ঘটে। এটি মূলত defer-কে ফাংশনের শেষে রাখা সাধারণ কোড থেকে আলাদা করে, যা তাড়াতাড়ি বেরিয়ে যাওয়ার সময় এড়িয়ে যাওয়া যেতে পারে।
ক্রিস ল্যাটনার (Swift স্রষ্টা, 2015)-এর একটি নিবন্ধ অনুসারে, defer অন্যান্য ভাষায় অনুরূপ নির্মাণ দ্বারা অনুপ্রাণিত হয়েছিল — Go-তে defer, Java/Python-এ finally, C++-এ scope guard — কিন্তু একটি গুরুত্বপূর্ণ পার্থক্যের সাথে: Swift-এ, defer সুযোগের শেষে কার্যকর হয়, try-catch ব্লকের পরপরই নয়। এটি একাধিক প্রস্থান পয়েন্টযুক্ত ফাংশনে পরিষ্কারের জন্য আরও পূর্বাভাসযোগ্য আচরণ প্রদান করে।
প্রতিসম সম্পদ পরিচালনার জন্য defer ব্যবহার করুন: ফাইল খুলুন → defer { close }, লক অর্জন করুন → defer { unlock }। এই প্যাটার্ন গ্যারান্টি দেয় যে কোনো পরিস্থিতিতে সম্পদ মুক্তি কখনো মিস হবে না।
যখন একই সুযোগে একাধিক defer ঘোষিত হয়, তখন সেগুলি ঘোষণার বিপরীত ক্রমে কার্যকর হয় (LIFO — Last In, First Out)। এর মানে হল শেষ ঘোষিত defer প্রথমে চলে, এবং প্রথম ঘোষিত শেষ চলে:
func exampleDeferOrder() {
defer { print("প্রথম defer") }
defer { print("দ্বিতীয় defer") }
defer { print("তৃতীয় defer") }
print("ফাংশন বডি")
}
// আউটপুট:
// ফাংশন বডি
// তৃতীয় defer
// দ্বিতীয় defer
// প্রথম defer
LIFO ক্রম নেস্টেড সম্পদের সঠিক পরিচালনার জন্য গুরুত্বপূর্ণ। যদি ফাইল A প্রথমে খোলা হয়, তারপর ফাইল B, তবে সেগুলিকে বিপরীত ক্রমে মুক্ত করতে হবে: প্রথমে B, তারপর A। defer-এর সাথে, এটি স্বয়ংক্রিয়ভাবে ঘটে — প্রতিটি সম্পদ খোলার পরপরই একটি defer ঘোষণা করুন, এবং ফাংশনে প্রস্থান পয়েন্টের সংখ্যা নির্বিশেষে পরিষ্কারের ক্রম সঠিক হবে।
Swift by Sundell (2024) অনুসারে, এই বৈশিষ্ট্যটি defer-কে নেস্টেড লক এবং লেনদেনের জন্য আদর্শ করে তোলে: লক অর্জন করুন → defer { unlock } → পরবর্তী অর্জন করুন → defer { unlock }। LIFO গ্যারান্টি দেয় যে লকগুলি অর্জনের বিপরীত ক্রমে মুক্তি পায়, ডেডলক প্রতিরোধ করে।
defer-এর প্রধান ব্যবহারের ক্ষেত্র হল সম্পদের নিশ্চিত পরিষ্কার। ফাইল সিস্টেমের সাথে কাজ করার কথা বিবেচনা করুন। FileHandle-এর মাধ্যমে একটি ফাইল খোলার জন্য স্পষ্টভাবে বন্ধ করার প্রয়োজন — defer গ্যারান্টি দেয় যে কোনো পরিস্থিতিতে close কল করা হবে:
func readFile(path: String) throws -> String {
let handle = try FileHandle(forReadingFrom: URL(fileURLWithPath: path))
defer { try? handle.close() }
let data = try handle.readToEnd()
guard let data else { throw FileError.empty() }
return String(data: data, encoding: .utf8) ?? ""
// throw বা return-এও handle.close() কল করা হবে
}
আরেকটি সাধারণ পরিস্থিতি হল লোডিং ফ্ল্যাগ সহ UI অ্যানিমেশন। লোড শুরু করার আগে, ফ্ল্যাগ সেট করুন isLoading = true, এবং defer ফাংশন থেকে বের হওয়ার সময় এটি আবার false-এ সেট করে, অনুরোধের সাফল্য বা ব্যর্থতা নির্বিশেষে। এটি একটি অপরিচালিত ত্রুটির কারণে ফ্ল্যাগ true থাকা থেকে রোধ করে, যা ইন্টারফেসকে চিরতরে ব্লক করতে পারে।
Bitbucket Engineering Blog (2024) অনুসারে, defer প্রোফাইলিংয়ের জন্যও ব্যবহার করা হয়: ফাংশনের শুরুতে সময় রেকর্ড করুন, এবং defer-এ — পার্থক্য গণনা করুন এবং আউটপুট করুন। এটি ত্রুটিপূর্ণ সহ সমস্ত কার্যকর করার পথের জন্য সঠিক কর্মক্ষমতা পরিমাপ দেয়।
defer throws ফাংশনের সাথে কার্যকরভাবে কাজ করে। যখন একটি ফাংশন যে কোনো পর্যায়ে ত্রুটি নিক্ষেপ করতে পারে, defer প্রতিটি catch ব্লক বা guard তাড়াতাড়ি প্রস্থানে কোড নকল না করে পরিষ্কার নিশ্চিত করে:
func processTransaction() throws {
let db = try openDatabase()
defer { closeDatabase(db) }
let user = try fetchUser(from: db)
defer { logAudit(user) }
let result = try performPayment(user)
sendNotification(result)
// closeDatabase(db) এবং logAudit(user) কল করা হবে
// যেকোনো throw বা return-এ
}
গুরুত্বপূর্ণ: defer নিয়ন্ত্রণ catch ব্লক থেকে স্থানান্তরিত করার আগে কার্যকর হয়, কিন্তু ত্রুটি ঘটার পরে। যদি defer-এর ভিতরে কোনো ত্রুটি নিক্ষেপ করা হয়, Swift defer-এর ভিতরে সরাসরি try ব্যবহারের অনুমতি দেয় না — আপনার প্রয়োজন try? বা try!। Apple ডকুমেন্টেশন অনুসারে, Swift ত্রুটিকে defer থেকে বেরিয়ে যাওয়ার অনুমতি দেয় না, কারণ এটি ব্লকের কার্যকর করার গ্যারান্টি লঙ্ঘন করবে।
সম্পদ অর্জনের পরপরই defer রাখুন। এটি নৈকট্যের নীতি অনুসরণ করে: পাঠক অর্জন এবং মুক্তি একসাথে দেখেন, যা কোড নির্ভরযোগ্যতা উন্নত করে এবং কোড পর্যালোচনা সহজ করে।
defer যে সুযোগে ঘোষিত হয় তা থেকে বেরিয়ে যাওয়ার সময় কার্যকর হয়। যদি defer একটি do ব্লকের ভিতরে ঘোষিত হয়, তবে এটি সেই ব্লক থেকে বেরিয়ে যাওয়ার সময় কার্যকর হয়, বাইরের ফাংশন থেকে নয়। যদি একটি for লুপের ভিতরে থাকে — প্রতিটি পুনরাবৃত্তিতে:
func scopeExample() {
print("start")
do {
defer { print("do-ব্লক defer") }
print("inside do")
}
// "do-ব্লক defer" এখানে প্রিন্ট হয়
print("after do")
}
// আউটপুট: start, inside do, do-ব্লক defer, after do
for i in 1...3 {
defer { print("end iteration \(i)") }
print("iteration \(i)")
}
// আউটপুট: iteration 1, end iteration 1, iteration 2, end iteration 2, ...
defer দ্বারা ক্যাপচার করা ভেরিয়েবলগুলি সুযোগ থেকে বের হওয়ার মুহূর্তে পড়া হয়, defer ঘোষণার মুহূর্তে নয়। যদি defer ঘোষণা এবং সুযোগের শেষের মধ্যে কোনো ভেরিয়েবল পরিবর্তিত হয়, defer সর্বশেষ মান দেখতে পাবে। এটি ক্লোজার থেকে একটি গুরুত্বপূর্ণ পার্থক্য, যেখানে ক্যাপচার তৈরি করার সময় স্থির হয়। সাবধান থাকুন: defer ঘোষণা করার পরে ভেরিয়েবলের পরিবর্তন তার কার্যকর করাকে প্রভাবিত করবে।
প্রথম ভুল — LIFO ছাড়া অন্য কার্যকর করার ক্রম ধরে নেওয়া। যদি পরিষ্কারের ক্রম গুরুত্বপূর্ণ হয় এবং defer ভুল ক্রমে ঘোষিত হয়, তাহলে সম্পদ নির্ভরতা লঙ্ঘনের সাথে মুক্তি পেতে পারে। সমাধান: প্রতিটি সম্পদ অর্জনের পরপরই defer ঘোষণা করুন। দ্বিতীয় সম্পদ খোলা হয়েছে → defer { close second } প্রথমটি বন্ধ হওয়ার আগে।
দ্বিতীয় ভুল — পরিষ্কারের সাথে সম্পর্কহীন যুক্তির জন্য defer ব্যবহার করা। defer নিশ্চিত পরিষ্কারের জন্য, প্রধান প্রবাহ নিয়ন্ত্রণের জন্য নয়। যদি defer-এর ভিতরের কোড রিটার্ন মানকে প্রভাবিত করে, এটি প্রায় সবসময়ই একটি ভুল। defer একটি ফাংশনের রিটার্ন মান পরিবর্তন করতে পারে না (Java finally-এর বিপরীতে, যেখানে finally-তে return আসল return-কে ওভাররাইট করে)।
তৃতীয় ভুল — defer থেকে ত্রুটি নিক্ষেপ করা। Swift defer-এর ভিতরে try নিষিদ্ধ করে যদি ত্রুটি বাইরে ছড়িয়ে যেতে পারে। সেই অপারেশনগুলির জন্য try? বা try! ব্যবহার করুন যা ত্রুটি নিক্ষেপ করতে পারে, বা সেগুলিকে throws ছাড়া একটি আলাদা ফাংশনে মোড়ানো। O’Reilly “Swift in Depth” (2025) অনুসারে, একটি ভাল অভ্যাস হল পরিষ্কার ফাংশনগুলিকে non-throwing করা বা defer-এর ভিতরে ত্রুটিগুলি পরিচালনা করা।
প্রায়শই জিজ্ঞাসিত প্রশ্ন
defer একটি Swift নির্মাণ যা বর্তমান সুযোগ শেষ না হওয়া পর্যন্ত একটি ব্লকের কার্যকর করা স্থগিত করে। ব্লকটি সর্বদা কার্যকর হয় — return, throw, break বা সাধারণ সমাপ্তিতে। এটি সম্পদের নিশ্চিত পরিষ্কারের জন্য ব্যবহৃত হয়: ফাইল বন্ধ করা, লক মুক্ত করা।
ঘোষণার বিপরীত ক্রমে (LIFO) — শেষ ঘোষিত defer প্রথমে চলে। এটি নেস্টেড সম্পদের সঠিক পরিষ্কার নিশ্চিত করে: যদি সম্পদ B, A-এর পরে খোলা হয়, তবে এটি A-এর আগে বন্ধ হবে, ইতিমধ্যে মুক্ত সম্পদের উপর নির্ভরতা প্রতিরোধ করে।
সরাসরি না — Swift defer থেকে ত্রুটি প্রচার প্রতিরোধ করে। সেই অপারেশনগুলির জন্য try? বা try! ব্যবহার করুন যা ত্রুটি নিক্ষেপ করতে পারে। সর্বোত্তম অভ্যাস হল পরিষ্কার ফাংশনগুলিকে non-throwing করা বা defer-এর ভিতরে ত্রুটিগুলি বাইরে প্রচার না করে পরিচালনা করা।
defer একটি সুযোগের সাথে আবদ্ধ এবং যে কোনো প্রস্থানে কার্যকর হয়, যার মধ্যে return, throw এবং break অন্তর্ভুক্ত। finally (অন্যান্য ভাষায়) try-catch-এর সাথে আবদ্ধ এবং শুধুমাত্র try উপস্থিত থাকলে কার্যকর হয়। Swift-এ finally নেই — defer এই পরিস্থিতিটি সম্পূর্ণরূপে কভার করে এবং যেকোনো সুযোগের জন্য কাজ করে, শুধুমাত্র ত্রুটি পরিচালনার জন্য নয়।
হ্যাঁ, defer সুযোগ থেকে বের হওয়ার মুহূর্তে ভেরিয়েবল পড়ে, ঘোষণার মুহূর্তে নয়। যদি defer ঘোষিত হওয়ার পরে কোনো ভেরিয়েবল পরিবর্তিত হয়, defer ব্লক সর্বশেষ মান দেখতে পাবে। এটি সাধারণ ক্লোজার থেকে আলাদা, যেখানে ক্যাপচার তৈরি করার সময় স্থির হয়।
সারাংশ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন