@MainActor Swift भाषा में एक वैश्विक अभिनेता (ग्लोबल एक्टर) है जो मुख्य थ्रेड पर कोड निष्पादन की गारंटी देता है। Apple Developer, 2024 के अनुसार, @MainActor UI के साथ काम करते समय मुख्य थ्रेड पर स्विच करने को स्वचालित करता है, डेवलपर को DispatchQueue.main.async को मैन्युअल रूप से कॉल करने से मुक्त करता है। यह एनोटेशन Swift 5.5 में async/await सिस्टम के साथ दिखाई दिया।
मुख्य बिंदु
@MainActor Swift में एक वैश्विक अभिनेता है जो अभिनेताओं के गुणों को एप्लिकेशन के मुख्य थ्रेड पर निष्पादन की गारंटी के साथ जोड़ता है। यह Swift 5.5 में async/await और संरचित समवर्तीता के साथ प्रस्तुत Swift समवर्तीता प्रणाली का हिस्सा है। एनोटेशन डेवलपर को मैन्युअल थ्रेड स्विचिंग के बारे में न सोचने देता है और UI त्रुटियों की संख्या को कम करता है।
Swift में अभिनेता एक संदर्भ प्रकार है जो अपनी स्थिति को अलग करता है और गारंटी देता है कि केवल एक थ्रेड इसे संशोधित कर सकता है। @MainActor एक विशेष वैश्विक अभिनेता है जिसका निष्पादक मुख्य थ्रेड है। @MainActor से चिह्नित कोई भी कोड मुख्य थ्रेड पर निष्पादित होता है — भले ही वह पृष्ठभूमि कार्य से कॉल किया गया हो।
@MainActor से पहले, डेवलपर DispatchQueue.main.async के माध्यम से मैन्युअल रूप से मुख्य थ्रेड पर स्विच करते थे। यह लगातार त्रुटियों का स्रोत था: डेवलपर स्विच करना भूल जाते थे, जिसके परिणामस्वरूप मुख्य थ्रेड पर UI अपडेट न होने के कारण क्रैश होते थे। @MainActor इस समस्या को टाइप सिस्टम स्तर पर हल करता है।
iOS एप्लिकेशन में अधिकांश बगों का स्रोत UI असुरक्षा है — पृष्ठभूमि थ्रेड से इंटरफ़ेस को अपडेट करना। Apple ने @MainActor को Swift Concurrency में बनाया ताकि मुख्य थ्रेड पर स्विच करना स्वचालित और कंपाइलर-जांच योग्य हो, जिससे रनटाइम त्रुटियों की एक पूरी श्रेणी समाप्त हो जाए।
@MainActor का काम करने का सिद्धांत Swift Concurrency निष्पादन प्रणाली पर आधारित है। जब कोई थ्रेड @MainActor से चिह्नित फ़ंक्शन को कॉल करता है, तो शेड्यूलर इसे वर्तमान निष्पादक पर निलंबित करता है और मुख्य थ्रेड पर फिर से शुरू करता है। कंपाइलर कॉल सीमाओं को ट्रैक करता है और सुरक्षा की गारंटी देता है।
@MainActor का निष्पादन MainActor.shared द्वारा संभाला जाता है — एक निष्पादक जो एप्लिकेशन के मुख्य थ्रेड से जुड़ा होता है। जब एक अतुल्यकालिक फ़ंक्शन @MainActor से चिह्नित होता है, तो यह हमेशा इस निष्पादक पर फिर से शुरू होता है, भले ही मूल कार्य किस थ्रेड पर शुरू किया गया हो।
import SwiftUI
class ViewModel: ObservableObject {
@Published var items: [String] = []
@MainActor
func loadData() async {
let result = await fetchRemoteData()
items = result // सुरक्षित रूप से, MainActor मुख्य थ्रेड की गारंटी देता है
}
}
यदि कोई फ़ंक्शन @MainActor से चिह्नित है और किसी अन्य अतुल्यकालिक फ़ंक्शन को कॉल करता है, तो यह डिफ़ॉल्ट रूप से अभिनेता संदर्भ प्राप्त करता है। इसका मतलब है कि सभी नेस्टेड कॉल भी मुख्य थ्रेड पर निष्पादित होते हैं, जब तक कि अन्यथा निर्दिष्ट न किया गया हो। कंपाइलर इसे ट्रैक करता है और असंगत क्लोजर पास करने का प्रयास करने पर त्रुटि जारी करता है।
@MainActor और DispatchQueue.main की तुलना यह समझने में मदद करती है कि नया तंत्र अधिक सुरक्षित और सुविधाजनक क्यों माना जाता है, हालांकि दोनों एक ही कार्य को हल करते हैं — मुख्य थ्रेड पर कोड निष्पादित करना।
@MainActor कंपाइलर स्तर पर जाँच है। यदि आप किसी असुरक्षित संदर्भ से @MainActor फ़ंक्शन को कॉल करने का प्रयास करते हैं, तो कंपाइलर चेतावनी या त्रुटि जारी करेगा। DispatchQueue.main.async एक रनटाइम कॉल है: कोड कंपाइल होगा लेकिन पृष्ठभूमि थ्रेड से UI अपडेट करने का प्रयास करने पर रनटाइम पर क्रैश हो सकता है।
DispatchQueue.main.async क्यू में एक ब्लॉक जोड़ता है जो देरी से निष्पादित हो सकता है। @MainActor async/await के साथ अनावश्यक क्लोजर बनाए बिना सीधे निष्पादक स्विचिंग करता है। यह ओवरहेड को कम करता है और निष्पादन समय को अधिक पूर्वानुमानित बनाता है।
// पुराना दृष्टिकोण
DispatchQueue.main.async {
self.updateUI()
}
// @MainActor के साथ नया दृष्टिकोण
@MainActor
func updateUI() {
// मुख्य थ्रेड पर निष्पादित होता है
self.label.text = "अपडेट किया गया"
}
| मानदंड | @MainActor | DispatchQueue.main |
|---|---|---|
| जाँच | कंपाइलर | रनटाइम |
| सिंटैक्स | एनोटेशन (घोषणात्मक) | कॉल (आदेशात्मक) |
| ओवरहेड | कम (निष्पादक स्विचिंग) | मध्यम (क्लोजर + क्यू) |
| परीक्षण क्षमता | उच्च (MainActor.shared बदला जा सकता है) | निम्न (मॉक करना कठिन) |
वास्तविक iOS प्रोजेक्ट्स में, @MainActor का उपयोग ViewModel परतों, SwiftUI व्यू और UIKit कंट्रोलर में किया जाता है। एनोटेशन को अलग-अलग विधियों और पूरे प्रकार दोनों पर लागू किया जा सकता है।
किसी क्लास को @MainActor से चिह्नित करके, आप गारंटी देते हैं कि इसकी सभी विधियाँ और गुण केवल मुख्य थ्रेड पर ही सुलभ हैं। यह SwiftUI व्यू और ObservableObject क्लास के लिए विशेष रूप से सुविधाजनक है: आप बस class से पहले @MainActor जोड़ते हैं, और सभी @Published गुण सुरक्षित रूप से अपडेट होते हैं।
@MainActor
final class UserListViewModel: ObservableObject {
@Published var users: [User] = []
@Published var isLoading = false
func fetchUsers() async {
isLoading = true
users = await api.getUsers()
isLoading = false
}
}
पुराने UIKit कोड के साथ काम करते समय जहां थ्रेड स्विचिंग मैन्युअल थी, आप स्पष्ट स्विचिंग के लिए MainActor.run का उपयोग कर सकते हैं। यह पूरे कोडबेस को फिर से लिखे बिना Swift Concurrency में क्रमिक संक्रमण के लिए सुविधाजनक है।
await MainActor.run {
self.tableView.reloadData()
}
अपने सभी लाभों के बावजूद, @MainActor की कई सीमाएं हैं जिन्हें एप्लिकेशन आर्किटेक्चर डिज़ाइन करते समय विचार करना महत्वपूर्ण है। प्रयोज्यता की सीमाओं को समझना गलत उपयोग से बचने में मदद करता है।
यदि पूरी कॉल श्रृंखला @MainActor से चिह्नित है, तो कोई भी भारी कार्य मुख्य थ्रेड पर निष्पादित होगा, जिससे UI हैंग हो जाएगा। केवल UI परत को @MainActor से चिह्नित करने की अनुशंसा की जाती है, जबकि व्यावसायिक तर्क और नेटवर्क अनुरोधों को पृष्ठभूमि अभिनेताओं या वैश्विक निष्पादक पर छोड़ दिया जाना चाहिए।
पुराने कॉलबैक-आधारित API (उदाहरण के लिए, URLSession बिना async/await) अभिनेता संदर्भ का समर्थन नहीं करते हैं। एकीकरण के लिए CheckedContinuation के साथ रैपर की आवश्यकता होती है। साथ ही, @MainActor performSelector, target-action और UIKit के अन्य गैर-अतुल्यकालिक पैटर्न के साथ संगत नहीं है।
@MainActor के साथ एप्लिकेशन डीबग करते समय, रेस कंडीशन को पुन: उत्पन्न करना कठिन होता है क्योंकि कंपाइलर उनमें से कई को रनटाइम के बजाय बिल्ड समय पर रोकता है। हालांकि, यह सुरक्षा की झूठी भावना पैदा कर सकता है: साझा म्यूटेबल ऑब्जेक्ट्स (जैसे NSCache या साझा वैश्विक चर) के साथ गलत काम अभी भी संभव है यदि वे @MainActor से चिह्नित नहीं हैं और स्पष्ट सिंक्रनाइज़ेशन के बिना उपयोग किए जाते हैं।
@MainActor UI तर्क परीक्षण को काफी सरल बनाता है क्योंकि यह परीक्षणों में मैन्युअल रूप से थ्रेड स्विच करने की आवश्यकता को समाप्त करता है। हालांकि, यूनिट टेस्ट और UI टेस्ट लिखते समय विचार करने के लिए विशेषताएं हैं।
XCTest में, परीक्षण वातावरण स्वचालित रूप से मुख्य थ्रेड निष्पादक सेट करता है। जब कोई परीक्षण विधि मुख्य थ्रेड पर चलती है, तो @MainActor फ़ंक्शन को कॉल करने के लिए अतिरिक्त सेटअप की आवश्यकता नहीं होती — वे उसी संदर्भ में निष्पादित होते हैं। पृष्ठभूमि परिदृश्यों के परीक्षण के लिए, स्पष्ट प्राथमिकता और निष्पादक के साथ Task के अंदर MainActor.run का उपयोग करें, अलग से सत्यापित करें कि कोड पृष्ठभूमि से कॉल करने पर सही ढंग से काम करता है।
एक सामान्य दृष्टिकोण @MainActor के साथ ViewModel का परीक्षण करना है, जहां यह सत्यापित किया जाता है कि अतुल्यकालिक संचालन के बाद @Published गुण सही ढंग से अपडेट होते हैं। अभिनेता संदर्भ विरासत के लिए धन्यवाद, परीक्षण के अंदर await को कॉल करना अतिरिक्त DispatchQueue गारंटी या मैन्युअल संदर्भ स्विचिंग के बिना मुख्य थ्रेड पर निष्पादन की गारंटी देता है, जो परीक्षण लेखन को सरल बनाता है।
मौजूदा कोड को Swift Concurrency में रीफैक्टर करते समय, कंपाइलर के माध्यम से @MainActor अलगाव की जाँच करें: @MainActor संदर्भ से @MainActor के बिना सिंक्रोनस विधियों का कोई भी कॉल त्रुटि के रूप में चिह्नित किया जाता है। इस गुण का उपयोग प्रोजेक्ट को धीरे-धीरे async/await में माइग्रेट करने के लिए किया जाता है: आप ViewModel परत को @MainActor के रूप में चिह्नित करते हैं, और कंपाइलर उन सभी असुरक्षित कॉलों को हाइलाइट करता है जिन्हें पृष्ठभूमि अभिनेताओं में ले जाने की आवश्यकता है।
@MainActor निर्भरताओं के लिए मॉक बनाते समय, रिटर्न प्रकारों के साथ अतुल्यकालिक फ़ंक्शन घोषित करने वाले async विधियों वाले प्रोटोकॉल का उपयोग करें। यह अभिनेता अलगाव को तोड़े बिना नेटवर्क सेवाओं, डेटाबेस और अन्य बाहरी निर्भरताओं को बदलने की अनुमति देता है। कंपाइलर सत्यापित करता है कि मॉक अलगाव की सभी आवश्यकताओं को लागू करता है, पृष्ठभूमि परीक्षण थ्रेड से @MainActor कोड तक आकस्मिक पहुंच को रोकता है।
@MainActor कोड का समकालिक रूप से परीक्षण करते समय, अतुल्यकालिक संचालन के पूरा होने की प्रतीक्षा करने के लिए XCTestExpectation का उपयोग करें। परीक्षण में अपेक्षा सेट करें और एक क्लोजर के अंदर fulfillment को कॉल करें जो मुख्य थ्रेड पर निष्पादित होता है। यदि परीक्षण अनिश्चित काल के लिए हैंग होता है — तो संभवतः मुख्य थ्रेड पर कॉल नहीं हो रहा है, और आपको अभिनेता अलगाव की जाँच करने की आवश्यकता है। निष्पादन संदर्भ को डीबग करने के लिए, परीक्षण कोड के अंदर Thread.isMainThread जाँच जोड़ना उपयोगी है।
अक्सर पूछे जाने वाले प्रश्न
नहीं, केवल उन विधियों को चिह्नित करना पर्याप्त है जो UI को अपडेट करती हैं। हालांकि, यदि किसी क्लास में ऐसी कई विधियां हैं, तो पूरी क्लास में @MainActor जोड़ना आसान है। यह गारंटी देता है कि इसके सभी सदस्य मुख्य थ्रेड पर निष्पादित होते हैं और कोड रखरखाव को सरल बनाता है।
@MainActor मुख्य थ्रेड से जुड़े वैश्विक अभिनेता का एक विशिष्ट उदाहरण है। @globalActor आपके स्वयं के वैश्विक अभिनेता बनाने के लिए एक प्रोटोकॉल है। उदाहरण के लिए, यदि प्रोजेक्ट आर्किटेक्चर की आवश्यकता है तो आप पृष्ठभूमि थ्रेड पर कोड निष्पादित करने के लिए @BackgroundActor बना सकते हैं।
हां, @MainActor के साथ समकालिक फ़ंक्शन भी मुख्य थ्रेड पर निष्पादित होते हैं। हालांकि, @MainActor का मुख्य मूल्य async/await के साथ प्रकट होता है, जब कोई अतुल्यकालिक फ़ंक्शन DispatchQueue.main के माध्यम से मैन्युअल स्विचिंग के बिना स्वचालित रूप से मुख्य थ्रेड पर फिर से शुरू होता है।
Task.cancel() @MainActor कार्यों के साथ सामान्य कार्यों की तरह ही काम करता है। एक @MainActor कार्य Task.isCancelled की जाँच कर सकता है या CancellationError फेंक सकता है। रद्द करने पर, मुख्य थ्रेड ब्लॉक नहीं होता — कार्य निकटतम निलंबन बिंदु पर निष्पादन बंद कर देता है।
कंपाइलर सुरक्षा की गारंटी देता है: यदि आप पृष्ठभूमि संदर्भ से @MainActor फ़ंक्शन को कॉल करते हैं, तो कंपाइलर त्रुटि का संकेत देगा। अतुल्यकालिक कॉल के लिए, कॉल करने वाले कोड को await से चिह्नित करना पर्याप्त है, और निष्पादक स्वयं मुख्य थ्रेड पर स्विच हो जाएगा। समकालिक कॉल के लिए, MainActor.run के माध्यम से स्पष्ट स्विचिंग की आवश्यकता होती है।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें