SwiftUI-এ @AppStorage হল UserDefaults-এর সাথে কাজ করার জন্য একটি property wrapper যা স্বয়ংক্রিয়ভাবে মানকে UI-এর সাথে সিঙ্ক করে। @AppStorage-এর মাধ্যমে ঘোষিত একটি প্রপার্টি পরিবর্তন হলে, নতুন মান তাৎক্ষণিকভাবে UserDefaults-এ সংরক্ষিত হয়, এবং যখন UserDefaults বাহ্যিকভাবে — উইজেট বা এক্সটেনশন দ্বারা — পরিবর্তিত হয়, View স্বয়ংক্রিয়ভাবে পুনরায় আঁকে। Apple Developer Documentation (2025) অনুসারে, @AppStorage String, Int, Double, Bool, Data, URL এবং তাদের অপশনাল সংস্করণ সমর্থন করে, ম্যানুয়াল অবজারভেশন কোড ছাড়াই ব্যবহারকারীর সেটিংসের রিঅ্যাকটিভ স্টোরেজ প্রদান করে।
মূল বিষয়
@AppStorage হল Apple-এর iOS 14-এ প্রবর্তিত একটি property wrapper যা View প্রপার্টিকে UserDefaults-এর একটি কী-তে বাঁধে। প্রপার্টি পড়ার সময়, SwiftUI নির্দিষ্ট কী দ্বারা UserDefaults থেকে মান লোড করে। লেখার সময়, নতুন মান সংরক্ষণ করে এবং View-কে পুনরায় আঁকার বিজ্ঞপ্তি দেয়।
@AppStorage-এর আগে, ডেভেলপারদের onAppear-এ ম্যানুয়ালি UserDefaults পড়তে, UserDefaults.didChangeNotification-এ সাবস্ক্রাইব করতে এবং পরিবর্তনে @State আপডেট করতে হত। @AppStorage পুরো চক্রটি স্বয়ংক্রিয় করে: এক-লাইন ঘোষণা 15–20 লাইন boilerplate কোড প্রতিস্থাপন করে। তাছাড়া, @AppStorage দ্বিমুখী সিঙ্ক্রোনাইজেশন প্রদান করে — যদি অন্য প্রক্রিয়া (যেমন App Extension বা Widget) থেকে UserDefaults মান পরিবর্তিত হয়, View তবুও আপডেট পাবে।
স্থাপত্যগতভাবে, @AppStorage DynamicProperty হিসেবে বাস্তবায়িত, যা SwiftUI-কে নির্ভরতা ট্র্যাক করতে এবং পর্যবেক্ষিত মান পরিবর্তনে View পুনরায় আঁকতে দেয়। এটি ব্যবহারকারীর সেটিংস: ইন্টারফেস ভাষা, বৈশিষ্ট্য সক্রিয়/নিষ্ক্রিয়, শেষ নির্বাচিত ট্যাব, ব্যবহারকারীর নাম সংরক্ষণের জন্য আদর্শ করে তোলে।
যদিও @AppStorage অভ্যন্তরীণভাবে UserDefaults ব্যবহার করে, স্টোরেজ নিয়ে কাজ করার পদ্ধতি মৌলিকভাবে ভিন্ন। UserDefaults একটি নিম্ন-স্তরের API যার জন্য পড়া, লেখা এবং পরিবর্তন বিজ্ঞপ্তির ম্যানুয়াল ব্যবস্থাপনা প্রয়োজন। @AppStorage হল একটি SwiftUI অ্যাবস্ট্র্যাকশন যা বক্সের বাইরে রিঅ্যাকটিভ আচরণ প্রদান করে।
UserDefaults এককালীন অপারেশনের জন্য উপযুক্ত: অ্যাপ স্টার্টআপে সেটিংস লোড করা, অ্যানালিটিক্স লেখা, টোকেন ক্যাশ করা। @AppStorage সেটিংসের জন্য যা UI-কে রিঅ্যাকটিভভাবে আপডেট করা উচিত: থিম টগল, ভাষা নির্বাচন, ইন্টারফেস অবস্থা সংরক্ষণ। View-এর ভিতরে সরাসরি UserDefaults ব্যবহার করা একটি অ্যান্টি-প্যাটার্ন, কারণ অতিরিক্ত সাবস্ক্রিপশন ছাড়া View পরিবর্তন সম্পর্কে জানে না।
| প্যারামিটার | @AppStorage | UserDefaults |
|---|---|---|
| প্রতিক্রিয়াশীলতা | স্বয়ংক্রিয় | বিজ্ঞপ্তিতে সাবস্ক্রিপশন প্রয়োজন |
| Boilerplate | প্রতি প্রপার্টিতে 1 লাইন | প্রতি প্রপার্টিতে 15–20 লাইন |
| প্রকার | String, Int, Double, Bool, Data, URL | সব প্রকার + আর্কাইভ করা অবজেক্ট |
| কাস্টম প্রকার | RawRepresentable-এর মাধ্যমে | NSKeyedArchiver-এর মাধ্যমে |
| App Extension | স্বয়ংক্রিয় সিঙ্ক | ম্যানুয়াল সাবস্ক্রিপশন |
সরল সেটিংসের জন্য রিঅ্যাকটিভ UI সহ @AppStorage পছন্দের পছন্দ। জটিল ডেটার (অ্যারে, ডিকশনারি, কাস্টম অবজেক্ট) জন্য UserDefaults-কে @State এবং ম্যানুয়াল পরিবর্তন সাবস্ক্রিপশনের সাথে কম্বিনেশনে ব্যবহার করুন, বা স্ট্রাকচার্ড স্টোরেজের জন্য SwiftData / Core Data-তে সুইচ করুন।
@AppStorage স্ট্যান্ডার্ড প্রকার সমর্থন করে যা UserDefaults সরাসরি সিরিয়ালাইজ করতে পারে: String, Int, Double, Bool, Data, URL। প্রতিটি প্রকারের জন্য একটি অপশনাল সংস্করণ (String?, Int?, Double?, Bool?, Data?, URL?) রয়েছে, যা "সেট না" এবং "খালি মান"-এর মধ্যে পার্থক্য করতে দেয়।
RawRepresentable প্রোটোকল মেনে চলে এমন কাস্টম প্রকার সংরক্ষণের জন্য, @AppStorage স্বয়ংক্রিয়ভাবেও কাজ করে। যদি কোনো enum-এর rawValue String বা Int প্রকারের হয়, এটি সরাসরি ব্যবহার করা যেতে পারে: @AppStorage("theme") var theme: AppTheme = .system. SwiftUI স্বয়ংক্রিয়ভাবে rawValue-এর মাধ্যমে মান সিরিয়ালাইজ/ডিসিরিয়ালাইজ করে।
enum AppTheme: String {
case system, light, dark
}
struct SettingsView: View {
@AppStorage("username") var username: String = "Guest"
@AppStorage("launchCount") var launchCount: Int = 0
@AppStorage("isDarkMode") var isDarkMode: Bool = false
@AppStorage("appTheme") var theme: AppTheme = .system
@AppStorage("lastOpened") var lastOpened: Date? = nil
var body: some View {
Form {
TextField("Username", text: $username)
Toggle("Dark mode", isOn: $isDarkMode)
Text("\(launchCount) বার লঞ্চ হয়েছে")
}
}
}
উদাহরণটি বিভিন্ন @AppStorage প্রকার ব্যবহার করে: ডিফল্ট মান "Guest" সহ String, লঞ্চ কাউন্টারের জন্য Int, ডার্ক থিমের জন্য Bool, String প্রকারের rawValue সহ AppTheme enum, এবং শেষ খোলার সময়ের জন্য অপশনাল Date?। প্রতিটি প্রপার্টি প্রথম আর্গুমেন্ট হিসেবে নির্দিষ্ট UserDefaults কী-তে আবদ্ধ। প্রথম লঞ্চে স্টোরেজে কী না থাকলে ডিফল্ট মান ব্যবহার করা হয়।
@AppStorage-এর মূল সুবিধাগুলির মধ্যে একটি হল যেকোনো উৎস থেকে UserDefaults পরিবর্তনের স্বয়ংক্রিয় পর্যবেক্ষণ। যদি কোনো App Extension বা Widget মান পরিবর্তন করে, প্যারেন্ট অ্যাপে @AppStorage বিজ্ঞপ্তি পায় এবং View পুনরায় আঁকে। এটি KVO (Key-Value Observing) প্রক্রিয়ার মাধ্যমে অর্জিত হয় যা @AppStorage স্বয়ংক্রিয়ভাবে UserDefaults.didChangeNotification-এ সেটআপ করে।
ব্যবহারিকভাবে, এর অর্থ হল যদি ব্যবহারকারী Widget-এ কোনো সেটিং পরিবর্তন করে (উদাহরণস্বরূপ, ডার্ক থিম সক্রিয় করে), অ্যাপ তাৎক্ষণিকভাবে পরিবর্তনটি গ্রহণ করে। একই সিঙ্ক্রোনাইজেশন প্রধান অ্যাপ এবং Share Extension, Watch App বা Today Widget-এর মধ্যে কাজ করে। ডেভেলপারকে আন্তঃপ্রক্রিয়া ডেটা বিনিময়ের জন্য কোড লিখতে হবে না — @AppStorage এটি স্বয়ংক্রিয়ভাবে করে।
struct ThemeSettingView: View {
@AppStorage("isDarkMode") var isDarkMode: Bool = false
var body: some View {
VStack {
Toggle("Dark Mode", isOn: $isDarkMode)
.onChange(of: isDarkMode) { oldValue, newValue in
print("ডার্ক মোড পরিবর্তিত হয়ে \(newValue) হয়েছে")
}
}
}
}
Toggle @AppStorage-এর মাধ্যমে $isDarkMode-এর সাথে আবদ্ধ। টগল করলে, মান স্বয়ংক্রিয়ভাবে "isDarkMode" কী-র অধীনে UserDefaults-এ সংরক্ষিত হয়। .onChange মডিফায়ার পরিবর্তনে সাইড ইফেক্ট করার অনুমতি দেয় — উদাহরণস্বরূপ, অ্যানালিটিক্স পাঠানো বা অন্যান্য স্ক্রিনের UI আপডেট করা। যদি Widget একই কী পরিবর্তন করে, @AppStorage-ও onChange ট্রিগার করবে, যা অবস্থার ধারাবাহিকতা নিশ্চিত করে।
আসুন একটি সম্পূর্ণ অ্যাপ সেটিংস স্ক্রিন দেখি যা সমস্ত কনফিগারেশন সংরক্ষণের জন্য @AppStorage ব্যবহার করে। ফর্মটিতে বিভিন্ন ধরনের সেটিংস সহ বিভাগ রয়েছে: টেক্সট ফিল্ড, টগল, কাউন্টার — সমস্ত মান স্বয়ংক্রিয়ভাবে UserDefaults-এ সংরক্ষিত হয়।
struct AppSettingsView: View {
@AppStorage("displayName") var displayName = ""
@AppStorage("notificationsEnabled") var notificationsEnabled = true
@AppStorage("maxResults") var maxResults = 25
@AppStorage("selectedTab") var selectedTab = "home"
var body: some View {
NavigationStack {
Form {
Section(header: Text("প্রোফাইল")) {
TextField("Display name", text: $displayName)
}
Section(header: Text("পছন্দসমূহ")) {
Toggle("Enable notifications",
isOn: $notificationsEnabled)
Stepper("Max results: \(maxResults)",
value: $maxResults,
in: 10...100,
step: 5)
}
Section {
Button("সেটিংস রিসেট করুন") {
UserDefaults.standard.removePersistentDomain(
forName: Bundle.main.bundleIdentifier!)
}
.tint(.red)
}
}
.navigationTitle("Settings")
}
}
}
ফর্মটিতে বিভিন্ন প্রকারের চারটি @AppStorage প্রপার্টি রয়েছে: নামের জন্য String, বিজ্ঞপ্তির জন্য Bool, ফলাফলের সংখ্যার জন্য Int এবং নির্বাচিত ট্যাবের জন্য String। সমস্ত নিয়ন্ত্রণ Binding ($displayName, $notificationsEnabled, ইত্যাদি)-এর মাধ্যমে প্রপার্টির সাথে আবদ্ধ। "Reset settings" বাটন অ্যাপ ডোমেন সরিয়ে সমস্ত UserDefaults সাফ করে — তার পরে @AppStorage স্বয়ংক্রিয়ভাবে ডিফল্ট মানগুলিতে ফিরে আসে।
struct SharedSettingsView: View {
let sharedDefaults = UserDefaults(suiteName: "group.com.example.app")
@AppStorage("widgetTheme", store: UserDefaults(suiteName: "group.com.example.app")!)
var widgetTheme: String = "সিস্টেম"
@AppStorage("widgetColor", store: UserDefaults(suiteName: "group.com.example.app")!)
var widgetColor: String = "নীল"
var body: some View {
Form {
Picker("Widget theme", selection: $widgetTheme) {
Text("সিস্টেম").tag("system")
Text("হালকা").tag("হালকা")
Text("ডার্ক").tag("ডার্ক")
}
Picker("Accent color", selection: $widgetColor) {
Text("নীল").tag("blue")
Text("সবুজ").tag("সবুজ")
Text("লাল").tag("লাল")
}
}
}
}
App Group-এর জন্য (অ্যাপ এবং এক্সটেনশনের মধ্যে শেয়ার্ড স্টোরেজ) @AppStorage store প্যারামিটার গ্রহণ করে: UserDefaults(suiteName:)। মানগুলি শেয়ার্ড কন্টেইনারে সংরক্ষিত হয় যা প্রধান অ্যাপ, Widget, Watch App এবং একই গ্রুপের অন্যান্য এক্সটেনশনের জন্য উপলব্ধ। Widget এই সেটিংস পড়তে পারে, এবং যখন সেগুলি অ্যাপে পরিবর্তিত হয়, Widget UserDefaults পর্যবেক্ষণ প্রক্রিয়ার মাধ্যমে স্বয়ংক্রিয়ভাবে আপডেট হয়।
প্রায়শই জিজ্ঞাসিত প্রশ্ন
@State মান শুধুমাত্র মেমোরিতে সংরক্ষণ করে এবং অ্যাপ পুনরায় চালু হলে রিসেট হয়। @AppStorage মান UserDefaults-এ সংরক্ষণ করে এবং পরবর্তী লঞ্চে পুনরুদ্ধার করে। অস্থায়ী স্ক্রিন ডেটার জন্য @State ব্যবহার করুন, সেটিংসের জন্য @AppStorage যা পুনরায় চালুর পরেও টিকে থাকা উচিত।
হ্যাঁ, যদি Enum String বা Int প্রকারের rawValue সহ RawRepresentable প্রোটোকল প্রয়োগ করে। উদাহরণ: @AppStorage("theme") var theme: AppTheme = .system. SwiftUI স্বয়ংক্রিয়ভাবে rawValue-এর মাধ্যমে enum সিরিয়ালাইজ করে এবং লোডে পুনরুদ্ধার করে।
স্ট্যান্ডার্ড স্টোরেজের জন্য UserDefaults.standard.removePersistentDomain(forName: Bundle.main.bundleIdentifier!) বা নির্দিষ্ট কী-র জন্য removeObject(forKey:) কল করুন। সাফ করার পরে, সমস্ত @AppStorage প্রপার্টি ঘোষণায় নির্দিষ্ট ডিফল্ট মানগুলিতে ফিরে আসবে।
হ্যাঁ, অ্যাপ এবং এক্সটেনশনের মধ্যে সিঙ্ক্রোনাইজেশনের জন্য App Group ব্যবহার করুন: @AppStorage("key", store: UserDefaults(suiteName: "group.com.example.app")!)। Widget, Share Extension এবং Watch App একই UserDefaults পড়তে এবং লিখতে পারে, এবং পরিবর্তনগুলি স্বয়ংক্রিয়ভাবে ট্র্যাক করা হয়।
@AppStorage UserDefaults ব্যবহার করে, যা ছোট পরিমাণ ডেটার জন্য ডিজাইন করা হয়েছে: সেটিংস, টোকেন, কাউন্টার। প্রস্তাবিত সীমা প্রতি অ্যাপে 100 KB পর্যন্ত। কাঠামোবদ্ধ বা বড় ডেটার (অবজেক্ট অ্যারে, মিডিয়া ফাইল) জন্য SwiftData, Core Data বা ফাইল সিস্টেম ব্যবহার করুন।
সারাংশ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন