@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 তৈরি করুন। একটি বিকল্প হল সেই ডেটার জন্য যা রেফারেন্স সেমান্টিক্স প্রয়োজন না, 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 অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন