@StateObject SwiftUI में एक property wrapper है जो View के पूरे जीवनचक्र में ObservableObject इंस्टेंस बनाता और उसका स्वामित्व रखता है। जब View पहली बार स्क्रीन पर दिखाई देती है, @StateObject ऑब्जेक्ट को आरंभ करता है और उसे तब तक संग्रहीत रखता है जब तक View मेमोरी से हटा नहीं दी जाती। यह सुनिश्चित करता है कि इंटरफ़ेस के पुनर्निर्माण पर डेटा रीसेट न हो — उदाहरण के लिए, थीम बदलने या पैरेंट View को अपडेट करने पर। Apple डेवलपर दस्तावेज़ीकरण (2025) के अनुसार, @StateObject को SwiftUI पदानुक्रम में ObservableObject के लिए प्राथमिक स्रोत (source of truth) के रूप में उपयोग किया जाना चाहिए, जबकि चाइल्ड Views पहले से बनाए गए ऑब्जेक्ट को @ObservedObject या @EnvironmentObject के माध्यम से प्राप्त करते हैं।
मुख्य बिंदु
@StateObject एक property wrapper है जो iOS 14 में पेश किया गया, जो View को ObservableObject प्रोटोकॉल का अनुपालन करने वाले वर्ग का इंस्टेंस बनाने और उसका स्वामित्व रखने की अनुमति देता है। @State के विपरीत, जो मान प्रकारों (structs) के साथ काम करता है, @StateObject संदर्भ प्रकारों — उन वर्गों के लिए डिज़ाइन किया गया है जो अपने गुणों में परिवर्तन के बारे में SwiftUI को सूचित कर सकते हैं।
जब कोई View @StateObject var viewModel: MyViewModel का उपयोग करती है, SwiftUI पहली बार View प्रदर्शित होने पर स्वचालित रूप से MyViewModel का इंस्टेंस बनाता है और इसे एक विशेष फ्रेमवर्क स्टोरेज में संग्रहीत करता है। प्रत्येक View अपडेट पर (उदाहरण के लिए, जब पैरेंट स्थिति बदलती है), SwiftUI ऑब्जेक्ट को पुनः नहीं बनाता — वह मौजूदा इंस्टेंस का उपयोग तब तक करता है जब तक View पदानुक्रम से हटा नहीं दी जाती।
Apple WWDC Session 10137 (2024) के अनुसार, @StateObject iOS 13 में मौजूद डेटा हानि की समस्या को हल करता है जब Views का पुनर्निर्माण होता था, जिससे डेवलपर्स को पैरेंट View में ObservableObject बनाने और इसे आरंभकर्ता के माध्यम से पास करने के लिए मजबूर होना पड़ता था। इससे कोड दोहराव और गलती से ऑब्जेक्ट के पुनः निर्माण का जोखिम होता था।
import SwiftUI
class CounterViewModel: ObservableObject {
@Published var count: Int = 0
func increment() {
count += 1
}
}
struct CounterView: View {
@StateObject var viewModel = CounterViewModel()
var body: some View {
VStack {
Text("Count: \(viewModel.count)")
Button("Increment", action: viewModel.increment)
}
}
}
@StateObject तंत्र SwiftUI के Combine फ्रेमवर्क के साथ एकीकरण पर आधारित है। जब ObservableObject अपने गुणों को @Published विशेषता से चिह्नित करता है, SwiftUI स्वचालित रूप से ObservableObject प्रोटोकॉल में निर्मित प्रकाशक के माध्यम से परिवर्तनों की सदस्यता लेता है। जब कोई प्रकाशित गुण बदलता है, ऑब्जेक्ट objectWillChange प्रकाशक के माध्यम से संकेत भेजता है, जो इस ऑब्जेक्ट का अवलोकन करने वाले सभी Views के पुनर्चित्रण को ट्रिगर करता है।
SwiftUI ObservableObject इंस्टेंस को एक विशेष स्टोरेज में संग्रहीत करता है जो एक विशिष्ट View इंस्टेंस से बंधा होता है। यह स्टोरेज पहले रेंडर के दौरान एक बार बनता है और View के नष्ट होने तक मौजूद रहता है। यही कारण है कि @StateObject संदर्भ स्थिरता की गारंटी देता है — SwiftUI मेमोरी को स्वचालित रूप से प्रबंधित करता है, बिना View के आरंभकर्ता पर निर्भर हुए।
objc.io — Thinking in SwiftUI (2025) के अनुसार, @StateObject का आंतरिक कार्यान्वयन @State के समान तंत्र का उपयोग करता है लेकिन संदर्भ प्रकारों के लिए: SwiftUI ऑब्जेक्ट के चारों ओर एक बॉक्सिंग रैपर बनाता है और अपने स्वयं के आवंटक के माध्यम से इसके जीवनचक्र का प्रबंधन करता है, जो लगातार View पदानुक्रम पुनर्निर्माण के लिए अनुकूलित है।
@StateObject और @ObservedObject के बीच मुख्य अंतर यह है कि ऑब्जेक्ट का मालिक कौन है। @StateObject ऑब्जेक्ट बनाता और संग्रहीत करता है — वह मालिक है। @ObservedObject केवल उस ऑब्जेक्ट का अवलोकन करता है जो कहीं और बनाया गया और आरंभकर्ता या गुण के माध्यम से पारित किया गया।
| विशेषता | @StateObject | @ObservedObject |
|---|---|---|
| स्वामित्व | ऑब्जेक्ट बनाता और उसका मालिक है | केवल अवलोकन करता है |
| आरंभीकरण | View के अंदर init/डिफ़ॉल्ट के माध्यम से | बाहरी, पैरामीटर के माध्यम से पारित |
| जीवनचक्र | View के जीवनचक्र से बंधा | View द्वारा नियंत्रित नहीं |
| पुनर्निर्माण | अपडेट पर पुनः नहीं बनता | बाहरी रूप से बदला जा सकता है |
| iOS संस्करण | iOS 14+ | iOS 13+ |
नियम सरल है: यदि View ObservableObject बनाती है — @StateObject का उपयोग करें। यदि View केवल पैरेंट से पहले से बना ऑब्जेक्ट प्राप्त करती है — @ObservedObject का उपयोग करें। इस नियम का उल्लंघन या तो डेटा हानि (यदि स्वामित्व के लिए @ObservedObject का उपयोग किया जाए) या अत्यधिक ऑब्जेक्ट निर्माण (यदि अवलोकन के लिए @StateObject का उपयोग किया जाए) की ओर ले जाता है।
@StateObject का उपयोग उन Views में किया जाना चाहिए जो एक विशिष्ट डेटा सेट के लिए सत्य का स्रोत हैं। विशिष्ट परिदृश्यों में अपने स्वयं के view model वाली स्क्रीन, नेविगेशन स्टैक की रूट स्क्रीन और अपनी स्वयं की स्थिति प्रबंधित करने वाले मोडल प्रस्तुतिकरण शामिल हैं।
struct ProfileView: View {
@StateObject var viewModel = ProfileViewModel()
var body: some View {
NavigationStack {
Form {
TextField("Name", text: $viewModel.name)
TextField("Email", text: $viewModel.email)
Button("Save") {
viewModel.saveProfile()
}
}
.navigationTitle("Profile")
}
}
}
@StateObject को पैरामीटर के साथ आरंभ करने के लिए विशेष सिंटैक्स की आवश्यकता होती है, क्योंकि SwiftUI ऑब्जेक्ट निर्माण स्वयं प्रबंधित करता है। आप केवल आरंभकर्ता को पैरामीटर पास नहीं कर सकते — आपको एक एस्केपिंग क्लोज़र या अलग फ़ैक्टरी विधि का उपयोग करना होगा।
Swift by Sundell (2024) के अनुसार, सबसे साफ तरीका फ़ैक्टरी विधि या क्लोज़र का उपयोग करना है जिसे SwiftUI पहली बार ऑब्जेक्ट बनाते समय कॉल करेगा। वैकल्पिक दृष्टिकोण पैरेंट View में ObservableObject को आरंभ करना और इसे मानक आरंभकर्ता का उपयोग करके @StateObject के माध्यम से पास करना है।
class UserViewModel: ObservableObject {
@Published var user: User
init(user: User) {
self.user = user
}
}
struct UserDetailView: View {
@StateObject var viewModel: UserViewModel
init(user: User) {
_viewModel = StateObject(wrappedValue: UserViewModel(user: user))
}
var body: some View {
Text(viewModel.user.name)
}
}
यह याद रखना महत्वपूर्ण है कि @StateObject के साथ View आरंभकर्ता को property wrapper तक पहुँचने के लिए गुण नाम से पहले अंडरस्कोर (_viewModel) का उपयोग करना चाहिए, न कि इसके मान का। यह आरंभकर्ताओं में property wrappers के साथ काम करने के लिए एक मानक Swift पैटर्न है।
सबसे आम गलती उस View के लिए जिसे ऑब्जेक्ट का स्वामित्व रखना चाहिए, @StateObject के बजाय @ObservedObject का उपयोग करना है। इस मामले में, हर बार जब पैरेंट का पुनर्निर्माण होता है, ऑब्जेक्ट पुनः बनाया जाएगा, जिससे सभी संचित डेटा का नुकसान होगा। यह गलती NavigationStack या TabView के साथ जटिल पदानुक्रमों में विशेष रूप से कपटी है।
इन समस्याओं से बचने के लिए, एक सरल नियम का पालन करें: प्रति सत्य स्रोत एक @StateObject। यदि डेटा को कई स्क्रीनों में साझा किया जाना चाहिए — रूट View में एक बार @StateObject बनाएँ और इसे @ObservedObject या @EnvironmentObject के माध्यम से चाइल्ड तत्वों को पास करें।
// ❌ Wrong: @ObservedObject for owning an object
struct BadView: View {
@ObservedObject var vm = ViewModel() // will be recreated on each update!
}
// ✅ Correct: @StateObject for owning
struct GoodView: View {
@StateObject var vm = ViewModel() // created once for View lifetime
}
अक्सर पूछे जाने वाले प्रश्न
@State मान प्रकारों (structs, स्ट्रिंग, संख्याएँ) के साथ काम करता है और मान को सीधे SwiftUI स्टोरेज में संग्रहीत करता है। @StateObject संदर्भ प्रकारों — ObservableObject का अनुपालन करने वाले वर्गों के साथ काम करता है। @State सरल स्थानीय स्थितियों के लिए उपयुक्त है, @StateObject तर्क और प्रकाशित गुणों वाले जटिल ऑब्जेक्ट के लिए।
नहीं, @StateObject केवल iOS 14 और उससे ऊपर उपलब्ध है। iOS 13 के लिए, @ObservedObject का उपयोग करें और मैन्युअल जीवनचक्र प्रबंधन के साथ @State के माध्यम से पैरेंट View में ObservableObject बनाएँ। एक विकल्प उन डेटा के लिए जिन्हें संदर्भ अर्थशास्त्र (reference semantics) की आवश्यकता नहीं है, class के बजाय struct के साथ @State का उपयोग करना है।
चाइल्ड View अपनी स्वयं की प्रतिलिपि ObservableObject की बनाएगा, जो पैरेंट से पूरी तरह स्वतंत्र होगी। एक में परिवर्तन दूसरे को प्रभावित नहीं करेगा। यह लगभग हमेशा एक गलती है: पैरेंट से ऑब्जेक्ट प्राप्त करने के लिए @ObservedObject का उपयोग करें और View के अंदर नया ऑब्जेक्ट बनाने के लिए केवल @StateObject का उपयोग करें।
ऑब्जेक्ट तब नष्ट होता है जब उसे बनाने वाली View पूरी तरह से SwiftUI पदानुक्रम से हटा दी जाती है। NavigationStack में स्क्रीन के लिए, यह नेविगेशन स्टैक से पॉप पर होता है। मोडल विंडो के लिए — जब इसे बंद किया जाता है। TabView के लिए — टैब बदलने पर, यदि View कैश नहीं की गई है।
अंडरस्कोर के माध्यम से property wrapper तक पहुँच के साथ कस्टम init का उपयोग करें: _viewModel = StateObject(wrappedValue: MyViewModel(param: value))। यह पैटर्न ObservableObject में कोई भी पैरामीटर पास करने की अनुमति देता है, साथ ही View के जीवनकाल में एक बार ऑब्जेक्ट निर्माण की गारंटी बनाए रखता है।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें