.task { } হল SwiftUI-তে iOS 15-এ প্রবর্তিত একটি মডিফায়ার যা View প্রদর্শিত হলে একটি অ্যাসিঙ্ক্রোনাস অপারেশন শুরু করে এবং View অদৃশ্য হলে স্বয়ংক্রিয়ভাবে তা বাতিল করে। .onAppear-এর বিপরীতে, যা বাতিল করার ক্ষমতা ছাড়াই সিঙ্ক্রোনাস কোড নির্বাহ করে, .task async/await কনটেক্সটের সাথে কাজ করে এবং View-এর জীবনচক্র বিবেচনা করে: View অদৃশ্য হলে, SwiftUI তৈরি করা Task-এ cancel() কল করে। এটি মেমরি লিক এবং View-এর আর আপডেটের প্রয়োজন না হওয়া সত্ত্বেও অপারেশন নির্বাহ হওয়া প্রতিরোধ করে। Apple WWDC Session 10132 — Meet async/await in SwiftUI (2024) অনুসারে, .task হল SwiftUI-তে ডেটা লোড করার পছন্দের উপায় কারণ এটি Structured Concurrency-এর সাথে নিরাপদে কাজ করে এবং অ্যাসিঙ্ক্রোনাস অপারেশনের জীবনকাল স্বয়ংক্রিয়ভাবে পরিচালনা করে।
মূল পয়েন্ট
.task { } হল একটি View মডিফায়ার যা View স্ক্রিনে প্রদর্শিত হলে async কনটেক্সটে একটি Task তৈরি করে। SwiftUI প্রদত্ত ক্লোজারটি ব্যাকগ্রাউন্ড থ্রেডে নির্বাহ করে, মূল থ্রেডটি UI অপারেশনের জন্য মুক্ত রাখে। যখন View অদৃশ্য হয়, SwiftUI Structured Concurrency মেকানিজমের মাধ্যমে স্বয়ংক্রিয়ভাবে Task বাতিল করে — এটি নিশ্চিত করে যে অ্যাসিঙ্ক্রোনাস অপারেশন তার ফলাফলের আর প্রয়োজন না থাকলেও নির্বাহ হতে থাকে না।
Apple — Swift Programming Language (2025) অনুসারে, .task Swift 5.5-এ প্রবর্তিত Structured Concurrency-এর ধারণা ব্যবহার করে। প্রতিটি .task প্যারেন্ট View-এর টাস্কের অধীনে একটি চাইল্ড টাস্ক তৈরি করে। যদি প্যারেন্ট টাস্ক বাতিল হয় (View অদৃশ্য হয়), তবে সমস্ত চাইল্ড টাস্কও স্বয়ংক্রিয়ভাবে বাতিল হয়। এটি DispatchWorkItem বা AnyCancellable-এর রেফারেন্স ম্যানুয়ালি সংরক্ষণের তুলনায় অ্যাসিঙ্ক্রোনাস অপারেশনের জীবনচক্র পরিচালনাকে মৌলিকভাবে সহজ করে।
@State + .onAppear-এ ম্যানুয়াল কলের ঐতিহ্যগত পদ্ধতির বিপরীতে, .task-এর পরবর্তী বাতিলের জন্য Task-এর রেফারেন্স সংরক্ষণের প্রয়োজন হয় না। SwiftUI এটি স্বয়ংক্রিয়ভাবে করে, বয়লারপ্লেট কোড হ্রাস করে এবং টাস্ক বাতিল করতে ভুলে যাওয়ার ঝুঁকি দূর করে।
struct ArticlesView: View {
@State var articles: [Article] = []
@State var error: Error?
var body: some View {
List(articles) { article in
Text(article.title)
}
.task {
do {
articles = await APIClient().fetchArticles()
} catch {
self.error = error
}
}
}
}
অনেক ডেভেলপার .onAppear-এ ডেটা লোড করতে অভ্যস্ত, কিন্তু async/await এবং .task-এর আগমনে এই পদ্ধতি পুরনো হয়ে গেছে। .onAppear কোড সিঙ্ক্রোনাসভাবে নির্বাহ করে — .onAppear-এর ভিতরে অ্যাসিঙ্ক্রোনাস অপারেশনের জন্য, কলটি Task { }-এ মোড়ানো এবং সম্ভাব্য বাতিলের জন্য ম্যানুয়ালি তার রেফারেন্স রাখা প্রয়োজন। .task এটি স্বয়ংক্রিয়ভাবে করে।
| বৈশিষ্ট্য | .task { } | .onAppear |
|---|---|---|
| Async কনটেক্সট | অন্তর্নির্মিত async/await | Task { } র্যাপার প্রয়োজন |
| স্বয়ংক্রিয় বাতিল | হ্যাঁ, View অদৃশ্য হলে | না, ম্যানুয়ালি বাস্তবায়ন করতে হবে |
| Structured Concurrency | সমর্থন করে | সমর্থন করে না |
| পুনরায় সক্রিয়করণ | শুধুমাত্র id পরিবর্তনে | প্রতিবার View প্রদর্শিত হলে |
| Apple সুপারিশ | পছন্দের উপায় | সিঙ্ক্রোনাস অপারেশনের জন্য |
.onAppear এখনও সিঙ্ক্রোনাস অপারেশনের জন্য useful — উদাহরণস্বরূপ, লগিং বা প্রাথমিক UI সেটআপ। কিন্তু অ্যাসিঙ্ক্রোনাস ডেটা লোডিং, নেটওয়ার্ক অনুরোধ, ডাটাবেস বা ফাইল সিস্টেম অপারেশনের জন্য .task ব্যবহার করুন। এটি আর্কিটেকচারের দৃষ্টিকোণ থেকে নিরাপদ এবং পরিষ্কার।
// ❌ পুরনো পদ্ধতি: .onAppear-এ বাতিল ছাড়া Task
var loadTask: Task<Void, Never>?
func body() { var body: some View { Text("") }
.onAppear {
loadTask = Task { await loadData() }
}
.onDisappear { loadTask?.cancel() }
// ✅ আধুনিক পদ্ধতি: .task বাতিল পরিচালনা করে
func body() { var body: some View { Text("") }
.task { await loadData() }
.task(id:) মডিফায়ার একটি অতিরিক্ত প্যারামিটার — শনাক্তকারী গ্রহণ করে। যখন শনাক্তকারীর মান পরিবর্তন হয়, SwiftUI বর্তমান টাস্ক বাতিল করে এবং নতুন শনাক্তকারী সহ একটি নতুন টাস্ক শুরু করে। এটি সেই স্ক্রিনগুলির জন্য আদর্শ যেখানে ডেটা একটি নির্বাচিত প্যারামিটারের উপর নির্ভর করে — উদাহরণস্বরূপ, বিভাগ অনুযায়ী নিবন্ধের তালিকা বা ID অনুযায়ী পণ্যের বিবরণ।
struct CategoryView: View {
let categoryId: Int
@State var items: [Item] = []
var body: some View {
List(items) { item in
Text(item.name)
}
.task(id: categoryId) {
await loadItems(for: categoryId)
}
}
func loadItems(for id: Int) async {
do {
items = await APIClient().fetchItems(categoryId: id)
} catch {
// ত্রুটি সামলান
}
}
}
যখন categoryId পরিবর্তন হয়, SwiftUI পূর্ববর্তী অনুরোধ বাতিল করে এবং নতুনটি শুরু করে। এটি দ্রুত বিভাগ স্যুইচিংয়ের সময় বিশেষভাবে গুরুত্বপূর্ণ — পুরনো অনুরোধগুলি স্টেট আপডেটের জন্য নতুনগুলির সাথে প্রতিযোগিতা করবে না। .task(id:) ছাড়া, আপনাকে .onChange-এর মাধ্যমে ম্যানুয়ালি পরিবর্তন ট্র্যাক করতে এবং Task ম্যানুয়ালি পরিচালনা করতে হবে।
যদিও .task View অদৃশ্য হলে টাস্ক স্বয়ংক্রিয়ভাবে বাতিল করে, অ্যাসিঙ্ক্রোনাস অপারেশনকে নিজেই সহযোগিতামূলকভাবে বাতিল পরীক্ষা করতে হবে। Swift একটি সহযোগিতামূলক বাতিল মডেল ব্যবহার করে — Task.cancel() জোর করে নির্বাহ বন্ধ করে না, বরং শুধুমাত্র isCancelled ফ্ল্যাগ সেট করে। টাস্কের ভিতরের কোডের সময়ে সময়ে এই ফ্ল্যাগ পরীক্ষা করা উচিত।
struct LoadingView: View {
@State var progress: Double = 0
var body: some View {
ProgressView(value: progress)
.task {
for i in 0..<100 {
// বাতিল পরীক্ষা করুন
try Task.checkCancellation()
await Task.sleep(nanoseconds: 50_000_000)
progress = Double(i + 1) / 100.0
}
}
}
}
Task.checkCancellation() CancellationError নিক্ষেপ করে যদি টাস্ক বাতিল করা হয়। এটি পরীক্ষার সবচেয়ে সহজ উপায় — এটি যেকোনো async কনটেক্সটে কাজ করে। বিকল্প হল ব্যয়বহুল অপারেশনের আগে Task.isCancelled ম্যানুয়ালি পরীক্ষা করা। URLSession-এর জন্য, নেটওয়ার্ক অনুরোধ টাস্ক বাতিল হলে স্বয়ংক্রিয়ভাবে বাতিল হয়, কারণ URLSession মূলত Structured Concurrency সমর্থন করে।
.task অনেক পরিস্থিতির জন্য উপযুক্ত: সাধারণ JSON লোডিং থেকে TaskGroup-এর সাথে জটিল সমান্তরাল অপারেশন পর্যন্ত। আসুন তিনটি সাধারণ ব্যবহারের দৃষ্টান্ত দেখি।
struct ProfileView: View {
@State var profile: Profile?
@State var isLoading = true
var body: some View {
Group {
if isLoading {
ProgressView()
} else if let profile {
Text(profile.name)
} else {
Text("লোড করতে ব্যর্থ")
}
}
.task {
defer { isLoading = false }
do {
profile = await APIClient().fetchProfile()
} catch {
// প্রোফাইল nil থাকে
}
}
}
}
struct DashboardView: View {
@State var stats: DashboardStats?
var body: some View {
Text("ড্যাশবোর্ড")
.task {
stats = await Task {
await withThrowingTaskGroup { group in
group.addTask { await API().fetchUsers() }
group.addTask { await API().fetchOrders() }
group.addTask { await API().fetchRevenue() }
return DashboardStats(
users: try await group.next(),
orders: try await group.next(),
revenue: try await group.next()
)
}
}.value
}
}
}
সবচেয়ে সাধারণ ভুল হল মূল থ্রেডে সুইচ না করেই .task-এর ভিতরে UI বৈশিষ্ট্য পরিবর্তন করা। যদিও SwiftUI async কনটেক্সটে @State পরিবর্তন করার সময় স্বয়ংক্রিয়ভাবে মূল থ্রেডে আপডেট ফিরিয়ে দেয়, .task-এর ভিতরে UIKit উপাদানগুলির সরাসরি হেরফের ক্র্যাশের কারণ হতে পারে।
// ❌ ত্রুটি: কোনো ত্রুটি পরিচালনা নেই
.task {
let data = await fetchData() // ত্রুটিতে ক্র্যাশ!
items = data
}
// ✅ সঠিক: do/catch
.task {
do {
items = await fetchData()
} catch {
errorMessage = error.localizedDescription
}
}
সচরাচর জিজ্ঞাসিত প্রশ্ন
.task স্বয়ংক্রিয়ভাবে View অদৃশ্য হলে টাস্ক বাতিল করে এবং Structured Concurrency সমর্থন করে। .onAppear-এ Task { }-এর জন্য টাস্কের রেফারেন্স ম্যানুয়ালি রাখা এবং .onDisappear-এ cancel() কল করা প্রয়োজন। .task পড়তেও সহজ — এটি স্পষ্টভাবে নির্দেশ করে যে ডেটা লোডিং View-এর জীবনচক্রের অংশ।
হ্যাঁ, AsyncSequence বা AsyncStream-এ সাবস্ক্রাইব করতে, .task-এর ভিতরে for await value in publisher.values ব্যবহার করুন। এটি Publisher.values এক্সটেনশনের মাধ্যমে async/await এবং Combine উভয়ের সাথেই কাজ করে। View অদৃশ্য হলে, পুনরাবৃত্তি স্বয়ংক্রিয়ভাবে শেষ হবে এবং সাবস্ক্রিপশন বাতিল হবে।
হ্যাঁ, যদি TabView-এর ভিতরে View প্রতিটি সুইচে পুনরায় তৈরি হয়। iOS 18 থেকে, TabView Views মেমোরিতে রাখতে পারে — এই ক্ষেত্রে .task পুনরায় শুরু হয় না। যদি প্রতিটি ট্যাব সুইচে ডেটা পুনরায় লোড করার প্রয়োজন হয়, ট্যাব শনাক্তকারী সহ .task(id:) ব্যবহার করুন।
SwiftUI View অদৃশ্য হলে টাস্ক বাতিল করবে। যদি URLSession অনুরোধ টাস্কের ভিতরে ছিল, তাও বাতিল হবে। যদি টাস্ক সহযোগিতামূলক বাতিল সমর্থন না করে (উদাহরণস্বরূপ, isCancelled পরীক্ষা না করে), এটি চলতে থাকবে, কিন্তু এর ফলাফল স্টেটে প্রযোজ্য হবে না কারণ View আর বিদ্যমান নেই।
হ্যাঁ, আপনি একটি View-তে একাধিক .task মডিফায়ার যোগ করতে পারেন। প্রতিটি একটি স্বাধীন টাস্ক তৈরি করে। এটি বিভিন্ন ডেটা উৎস পৃথক করার জন্য useful: প্রোফাইল লোড করার জন্য একটি .task, WebSocket-এ সাবস্ক্রাইব করার জন্য দ্বিতীয়টি, জিওলোকেশন মনিটর করার জন্য তৃতীয়টি।
সারসংক্ষেপ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন