.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 अभी भी सिंक्रोनस ऑपरेशन के लिए उपयोगी है — उदाहरण के लिए, लॉगिंग या प्रारंभिक 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 मॉडिफ़ायर जोड़ सकते हैं। प्रत्येक एक स्वतंत्र कार्य बनाता है। यह विभिन्न डेटा स्रोतों को अलग करने के लिए उपयोगी है: प्रोफ़ाइल लोड करने के लिए एक .task, WebSocket की सदस्यता लेने के लिए दूसरा, भू-स्थान की निगरानी के लिए तीसरा।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें