NSUserDefaults হলো iOS, watchOS, tvOS এবং macOS-এ একটি কী-ভ্যালু ডেটা স্টোরেজ, যা অ্যাপ্লিকেশন সেটিংস এবং কনফিগারেশন সংরক্ষণের জন্য ডিজাইন করা হয়েছে। ডেটা অ্যাপ্লিকেশন স্যান্ডবক্সের মধ্যে plist ফাইলে সংরক্ষিত হয় এবং NSUbiquitousKeyValueStore-এর মাধ্যমে স্বয়ংক্রিয়ভাবে iCloud-এর সাথে সিঙ্ক হয়। অফিসিয়াল ডকুমেন্টেশন অনুযায়ী Apple Developer, 2025, NSUserDefaults প্রিমিটিভ টাইপ সংরক্ষণ সমর্থন করে: String, Int, Bool, Float, Double, Data, Date, Array এবং Dictionary। Swift 3 থেকে ক্লাসটির নাম পরিবর্তন করে UserDefaults রাখা হয়েছে, কিন্তু এর Objective-C নাম NSUserDefaults কোড বেস এবং Apple ডকুমেন্টেশনে ব্যাপকভাবে ব্যবহৃত হচ্ছে।
মূল পয়েন্ট
NSUserDefaults (Swift-এ UserDefaults) হলো plist ফরম্যাটে কী-ভ্যালু জোড়া সংরক্ষণের জন্য Apple-এর বিল্ট-ইন মেকানিজম। এটি সমস্ত Apple প্ল্যাটফর্মে উপলব্ধ: iOS, iPadOS, watchOS, tvOS এবং macOS। এর প্রধান উদ্দেশ্য হলো ব্যবহারকারীর পছন্দ, ইন্টারফেস অবস্থা, প্রথম-লঞ্চ ফ্ল্যাগ, নির্বাচিত অপশন এবং অন্যান্য সাধারণ ডেটা সংরক্ষণ করা যা অ্যাপ্লিকেশন পুনরায় চালু করার পরেও টিকে থাকে।
প্রতিটি iOS অ্যাপ্লিকেশনের একটি বিচ্ছিন্ন স্যান্ডবক্স থাকে, এবং NSUserDefaults এই স্যান্ডবক্সের ভিতরে Library/Preferences ডিরেক্টরিতে Bundle Identifier নামক ফাইলে সংরক্ষিত হয়। plist ফাইলে কী-ভ্যালু জোড়া থাকে যেখানে কী হলো একটি স্ট্রিং এবং মান হলো সমর্থিত টাইপগুলির মধ্যে একটি। ফাইলের আকার সীমিত নয়, কিন্তু Apple UserDefaults-এ শুধুমাত্র সেটিংস সংরক্ষণের পরামর্শ দেয়, বড় পরিমাণের ডেটা নয়।
iOS 8 থেকে শুরু করে, NSUserDefaults App Groups সমর্থন করতে শুরু করেছে — একই ডেভেলপারের অ্যাপ্লিকেশন এবং তাদের এক্সটেনশন (উইজেট, watchOS কম্প্যানিয়ন অ্যাপ) এর মধ্যে শেয়ার্ড স্টোরেজ। এর জন্য App Group আইডেন্টিফায়ার সহ init?(suiteName:) ইনিশিয়ালাইজার ব্যবহার করা হয়। এটি উদাহরণস্বরূপ, Today উইজেটকে সেভ লজিক ডুপ্লিকেট না করেই মূল অ্যাপ্লিকেশন থেকে সেটিংস পড়তে দেয়।
ভৌতিকভাবে, NSUserDefaults একটি বাইনারি plist ফাইলে সংরক্ষিত হয়: {Sandbox}/Library/Preferences/com.example.myapp.plist। ফাইলটি কম্প্যাক্টনেস এবং পড়ার গতির জন্য বাইনারি plist ফরম্যাট (NSPropertyListBinaryFormat_v1_0) ব্যবহার করে। macOS-এ, ফাইলটি সামঞ্জস্যের জন্য XML ফরম্যাটে হতে পারে। Android-এর SharedPreferences-এর বিপরীতে, UserDefaults-এর plist ফাইলগুলি Dictionary এবং Array-এর মাধ্যমে নেস্টেড স্ট্রাকচার ধারণ করতে পারে।
NSUserDefaults ফাইলগুলি ডিফল্টভাবে এনক্রিপ্ট করা হয় না। ডেটা প্লেইন টেক্সটে সংরক্ষিত হয় এবং ডিভাইসে শারীরিক অ্যাক্সেস বা ব্যাকআপের মাধ্যমে পড়া যেতে পারে। সংবেদনশীল ডেটা (পাসওয়ার্ড, টোকেন, এনক্রিপশন কী) সংরক্ষণের জন্য, Apple অপারেটিং সিস্টেম স্তরে স্বয়ংক্রিয়ভাবে ডেটা এনক্রিপ্ট করে এমন Keychain ব্যবহার করার দৃঢ়ভাবে সুপারিশ করে।
NSUserDefaults পর্যায়ক্রমিক ডিস্ক সিঙ্ক্রোনাইজেশন সহ মেমরি ক্যাশিং নীতিতে কাজ করে। স্ট্যান্ডার্ড UserDefaults.standard ইনস্ট্যান্সে প্রথম অ্যাক্সেসে, সিস্টেম plist ফাইলটি Dictionary হিসেবে RAM-এ লোড করে। পরবর্তী সমস্ত রিডিং মেমরি থেকে সম্পাদিত হয়। লেখাও প্রথমে মেমরিতে ঘটে, ডিস্ক সিঙ্ক্রোনাইজেশন পর্যায়ক্রমিকভাবে ব্যাকগ্রাউন্ড থ্রেডে ঘটে।
লেখার অপারেশনগুলি set(_:forKey:) পদ্ধতি ব্যবহার করে, যা অপশনাল Any? টাইপের মান গ্রহণ করে। মান nil হতে পারে — একটি কী অপসারণ করতে ব্যবহৃত হয়। তাৎক্ষণিক ডিস্ক লেখার জন্য, পূর্বে synchronize() পদ্ধতি ব্যবহার করা হত, কিন্তু iOS 7 এবং OS X 10.9 থেকে এর আর প্রয়োজন নেই — সিস্টেম নিয়মিত বিরতিতে স্বয়ংক্রিয়ভাবে ডেটা সিঙ্ক করে। Apple তার ডকুমেন্টেশনে synchronize()-কে অপ্রয়োজনীয় ঘোষণা করেছে।
NSUserDefaults মান অনুসন্ধান সংগঠিত করার জন্য রেজিস্টার (ডোমেন) সিস্টেম ব্যবহার করে। যখন একটি অ্যাপ্লিকেশন কী দ্বারা মান অনুরোধ করে, UserDefaults একটি নির্দিষ্ট ক্রমে পর্যায়ক্রমে ডোমেনগুলি পরীক্ষা করে: প্রথমে NSArgumentDomain (কমান্ড-লাইন আর্গুমেন্ট), তারপর অ্যাপ্লিকেশন ডোমেন, তারপর NSGlobalDomain (সিস্টেম সেটিংস), তারপর ভাষা-নির্দিষ্ট ডোমেন এবং শেষে NSRegistrationDomain (register(defaults:) এর মাধ্যমে রেজিস্টার করা ডিফল্ট মান)।
import Foundation
// UserDefaults-এর স্ট্যান্ডার্ড ইনস্ট্যান্স
let defaults = UserDefaults.standard
// মান লেখা
defaults.set("আনা পেট্রোভা", forKey: "username")
defaults.set(28, forKey: "age")
defaults.set(true, forKey: "isLoggedIn")
// ডিফল্ট মান রেজিস্টার করা
defaults.register(defaults: [
"theme": "system",
"fontSize": 14
])
// ডিফল্ট মান ফেরত সহ পড়া
let theme = defaults.string(forKey: "theme") ?? "system"
let fontSize = defaults.integer(forKey: "fontSize")
NSRegistrationDomain হলো একটি প্রোগ্রামেটিক ডোমেন যা শুধুমাত্র মেমরিতে বিদ্যমান এবং ডিস্কে সংরক্ষিত হয় না। এটি ডিফল্ট মান সেট করতে ব্যবহৃত হয় যা ততক্ষণ পর্যন্ত প্রযোজ্য থাকে যতক্ষণ না অ্যাপ্লিকেশন অ্যাপ্লিকেশন ডোমেনে নিজস্ব মান লেখে। এটি ডিফল্ট সেটিংসের জন্য একটি একক কনফিগারেশন পয়েন্ট তৈরি করতে দেয় যা ডেভেলপমেন্টের সময় কেন্দ্রীয়ভাবে পরিবর্তন করা যেতে পারে।
NSUserDefaults ডেটা পড়া এবং লেখার জন্য টাইপকৃত পদ্ধতির একটি সেট প্রদান করে: string(forKey:), integer(forKey:), bool(forKey:), float(forKey:), double(forKey:), data(forKey:), array(forKey:), dictionary(forKey:) এবং object(forKey:)। প্রতিটি পড়ার পদ্ধতির জন্য সংরক্ষিত মানের স্বয়ংক্রিয় টাইপ নির্ধারণ সহ set(_:forKey:) লেখার পদ্ধতি রয়েছে। UserDefaults-এর Swift সংস্করণ শক্ত টাইপিং ব্যবহার করে, কিন্তু Objective-C সংস্করণ id গ্রহণ করে এবং ফেরত দেয়।
| পড়ার পদ্ধতি (Swift) | ডেটা টাইপ | ডিফল্ট মান |
|---|---|---|
| string(forKey:) | String? | nil |
| integer(forKey:) | Int | 0 |
| bool(forKey:) | Bool | false |
| float(forKey:) | Float | 0.0 |
| double(forKey:) | Double | 0.0 |
| data(forKey:) | Data? | nil |
NSUserDefaults-এ synchronize() পদ্ধতি সমস্ত পরিবর্তন মেমরি থেকে ডিস্কে জোর করে লেখে। iOS-এর আগের সংস্করণে, ডেটা স্থিরতা নিশ্চিত করতে প্রতিটি লেখার পরে এই পদ্ধতিটি কল করা প্রয়োজন ছিল। iOS 7 থেকে শুরু করে, সিস্টেম ব্যাকগ্রাউন্ড থ্রেডে স্বয়ংক্রিয়ভাবে UserDefaults সিঙ্ক করে, এবং Apple আনুষ্ঠানিকভাবে synchronize()-কে অপ্রয়োজনীয় ঘোষণা করেছে। এই পদ্ধতিটি কল করলে কোনো ত্রুটি হয় না কিন্তু কোনো অতিরিক্ত স্থিরতা গ্যারান্টি প্রদান করে না।
পরিবর্তন নিরীক্ষণের জন্য, NSUserDefaults UserDefaults.didChangeNotification নোটিফিকেশন এবং KVO পর্যবেক্ষণ পদ্ধতি addObserver(_:forKeyPath:options:context:) প্রদান করে। SwiftUI-তে, @AppStorage Property Wrapper উপলব্ধ, যা UserDefaults-এ মানকে UI আপডেটের সাথে স্বয়ংক্রিয়ভাবে সিঙ্ক করে। @AppStorage UserDefaults-এর মতো একই টাইপ সমর্থন করে এবং SwiftUI অ্যাপ্লিকেশনে সেটিংস নিয়ে কাজ করার পছন্দের উপায়।
// KVO-এর মাধ্যমে পরিবর্তন পর্যবেক্ষণ
class SettingsViewModel: NSObject {
override func observeValue(
forKeyPath keyPath: String?,
of object: Any?,
change: [NSKeyValueChangeKey: Any]?,
context: UnsafeMutableRawPointer?
) {
guard let keyPath else { return }
print("কী পরিবর্তিত হয়েছে: \(keyPath)")
}
}
// SwiftUI - AppStorage
struct SettingsView: View {
@AppStorage("theme") private var theme: String = "system"
var body: some View {
Picker("থিম", selection: $theme) {
Text("সিস্টেম").tag("system")
Text("হালকা").tag("light")
Text("গাঢ়").tag("dark")
}
}
}
App Groups (অ্যাপ্লিকেশন এবং এর এক্সটেনশনের মধ্যে শেয়ার্ড স্টোরেজ) নিয়ে কাজ করার জন্য, App Group আইডেন্টিফায়ার সহ UserDefaults(suiteName:) ইনিশিয়ালাইজার ব্যবহার করুন। উদাহরণস্বরূপ, “group.com.example.myapp”। এই ইনস্ট্যান্সে লেখা ডেটা মূল অ্যাপ্লিকেশন, উইজেট, watchOS কম্প্যানিয়ন অ্যাপ এবং একই App Group-এর অন্যান্য এক্সটেনশন থেকে অ্যাক্সেসযোগ্য। প্রতিটি suite ইনস্ট্যান্স একটি পৃথক plist ফাইলে সংরক্ষিত হয়।
এর সুবিধা এবং সরলতা সত্ত্বেও, NSUserDefaults iOS-এ সমস্ত ডেটা টাইপের জন্য একটি সার্বজনীন স্টোরেজ সমাধান নয়। ভলিউম, জটিলতা এবং নিরাপত্তা প্রয়োজনীয়তার উপর নির্ভর করে, Apple বেশ কয়েকটি বিকল্প প্রদান করে, প্রতিটি নির্দিষ্ট ব্যবহারের ক্ষেত্রে অপ্টিমাইজ করা।
| সমাধান | কখন ব্যবহার করবেন | সীমাবদ্ধতা |
|---|---|---|
| NSUserDefaults | ইন্টারফেস সেটিংস এবং কনফিগারেশন | বড় ডেটা বা গোপনীয়তার জন্য উপযুক্ত নয় |
| Keychain | পাসওয়ার্ড, টোকেন, এনক্রিপশন কী | ব্যবহারে জটিল, ধীর |
| CoreData | সম্পর্ক সহ কাঠামোবদ্ধ ডেটা | 10–20 সেটিংসের জন্য অতিরিক্ত |
| FileManager | ডকুমেন্ট, ছবি, বাইনারি ডেটা | ম্যানুয়াল ফাইল ব্যবস্থাপনা প্রয়োজন |
| CloudKit | ডিভাইসের মধ্যে ক্লাউড সিঙ্ক | iCloud অ্যাকাউন্ট এবং নেটওয়ার্ক সংযোগ প্রয়োজন |
Keychain হলো গোপনীয় ডেটার জন্য Apple-এর নিরাপদ স্টোরেজ। NSUserDefaults-এর বিপরীতে, Keychain-এর সমস্ত ডেটা সামঞ্জস্যপূর্ণ ডিভাইসে Secure Enclave থেকে হার্ডওয়্যার এনক্রিপশন ব্যবহার করে অপারেটিং সিস্টেম স্তরে এনক্রিপ্ট করা হয়। Keychain ডিভাইসের সাথে স্বয়ংক্রিয়ভাবে লক এবং আনলক হয় এবং Keychain Access Groups-এর মাধ্যমে একই ডেভেলপারের অ্যাপ্লিকেশনগুলির মধ্যে অ্যাক্সেস ভাগাভাগি সমর্থন করে।
Keychain-এর প্রধান ত্রুটি হলো API জটিলতা। শুধুমাত্র একটি স্ট্রিং সংরক্ষণের জন্য, আপনাকে বৈশিষ্ট্যগুলি নির্দিষ্ট করে SecItemAdd কোয়েরি তৈরি করতে হবে: ক্লাস (kSecClassGenericPassword), সার্ভিস (kSecAttrService), অ্যাকাউন্ট (kSecAttrAccount) এবং প্রকৃত ডেটা (kSecValueData)। Keychain-এর সাথে কাজ সহজ করার জন্য, KeychainAccess এবং SwiftKeychainWrapper-এর মতো থার্ড-পার্টি র্যাপার রয়েছে যা UserDefaults-এর মতো সুবিধাজনক কী-ভ্যালু ইন্টারফেস প্রদান করে।
একটি প্রায়োগিক উদাহরণ বিবেচনা করুন: NSUserDefaults ব্যবহার করে iOS অ্যাপ্লিকেশনে অনবোর্ডিং অবস্থা (স্বাগত স্ক্রিন) সংরক্ষণ এবং পুনরুদ্ধার করা। প্রথম লঞ্চে, ব্যবহারকারী অনবোর্ডিং স্ক্রিন দেখে; সেগুলি সম্পূর্ণ করার পরে, UserDefaults-এ একটি ফ্ল্যাগ সংরক্ষিত হয়। পরবর্তী লঞ্চে, অনবোর্ডিং এড়িয়ে যাওয়া হয়। SwiftUI-র জন্য @AppStorage ব্যবহার করা হয়; UIKit-এর জন্য UserDefaults.standard-এ সরাসরি অ্যাক্সেস।
আসুন একটি OnboardingManager তৈরি করি যা অনবোর্ডিং অবস্থা সংরক্ষণের জন্য UserDefaults-এর সাথে কাজকে এনক্যাপসুলেট করে। ম্যানেজার অবস্থা পরীক্ষা করার জন্য isOnboardingCompleted প্রপার্টি এবং ফ্ল্যাগ সেট করার জন্য markOnboardingCompleted পদ্ধতি প্রদান করে। টাইপো ত্রুটি প্রতিরোধ করতে স্টোরেজ কীটি একটি কনস্ট্যান্টে নিষ্কাশিত হয়েছে। ইউনিট টেস্টিং-এর জন্য, ম্যানেজার UserDefaultsProtocol ব্যবহার করে, যা বাস্তব স্টোরেজকে MockUserDefaults দিয়ে প্রতিস্থাপন করতে দেয়।
class OnboardingManager {
private let defaults: UserDefaults
private let hasSeenKey = "has_seen_onboarding"
init(defaults: UserDefaults = .standard) {
self.defaults = defaults
}
var isOnboardingCompleted: Bool {
defaults.bool(forKey: hasSeenKey)
}
func markOnboardingCompleted() {
defaults.set(true, forKey: hasSeenKey)
}
func resetOnboarding() {
defaults.removeObject(forKey: hasSeenKey)
}
}
// অ্যাপ্লিকেশনে ব্যবহার
let onboardingManager = OnboardingManager()
if !onboardingManager.isOnboardingCompleted {
showOnboarding()
} else {
showMainScreen()
}
আরও জটিল সেটিংস, যেমন একটি কাঠামোবদ্ধ Profile অবজেক্ট, সংরক্ষণের জন্য Codable প্রোটোকল এবং JSONEncoder/JSONDecoder ব্যবহার করার পরামর্শ দেওয়া হয়। অবজেক্টটি JSONEncoder-এর মাধ্যমে Data-তে সিরিয়ালাইজ হয়, set(_:forKey:) এর মাধ্যমে সংরক্ষিত হয়, এবং পড়ার সময় JSONDecoder-এর মাধ্যমে Data থেকে পুনরায় অবজেক্টে ডিসিরিয়ালাইজ হয়। এই পদ্ধতি টাইপ নিরাপত্তা না হারিয়ে UserDefaults-এ জটিল কাঠামো সংরক্ষণ করতে দেয়।
struct UserProfile: Codable {
let name: String
let age: Int
let preferences: [String: String]
}
extension UserDefaults {
func save<T: Codable>(_ value: T, forKey key: String) {
if let data = try? JSONEncoder().encode(value) {
set(data, forKey: key)
}
}
func load<T: Codable>(_ type: T.Type, forKey key: String) -> T? {
guard let data = data(forKey: key) else { return nil }
return try? JSONDecoder().decode(type, from: data)
}
}
// ব্যবহার
let profile = UserProfile(name: "আনা", age: 28, preferences: ["theme": "dark"])
UserDefaults.standard.save(profile, forKey: "user_profile")
let loaded = UserDefaults.standard.load(UserProfile.self, forKey: "user_profile")
মনে রাখা গুরুত্বপূর্ণ যে NSUserDefaults বড় পরিমাণের ডেটা সংরক্ষণের জন্য ডিজাইন করা হয়নি। Apple সংরক্ষিত ডেটা কয়েক ডজন কিলোবাইটে সীমাবদ্ধ রাখার পরামর্শ দেয়। বড় অবজেক্ট (ছবি, ডকুমেন্ট, সিরিয়ালাইজড মডেল) সংরক্ষণের জন্য Documents ডিরেক্টরি সহ FileManager বা CoreData ব্যবহার করুন। উপরন্তু, UserDefaults ডেটা স্কিমা ভার্সনিং সমর্থন করে না — যখন Codable মডেল কাঠামো পরিবর্তিত হয়, পুরানো ডেটা ডিসিরিয়ালাইজ হতে ব্যর্থ হতে পারে এবং এটি অ্যাপ্লিকেশন কোডে হ্যান্ডেল করা আবশ্যক।
সচরাচর জিজ্ঞাসা
দুটিই কী-ভ্যালু স্টোর, কিন্তু NSUserDefaults আরও বেশি টাইপ (Data, Date, Array, Dictionary) সমর্থন করে এবং স্বয়ংক্রিয়ভাবে iCloud-এর সাথে সিঙ্ক হয়। SharedPreferences ডেটা XML-এ সংরক্ষণ করে, NSUserDefaults plist ফরম্যাটে। NSUserDefaults-এ ক্যাসকেডিং অনুসন্ধান সহ ডোমেন সিস্টেম রয়েছে, যখন SharedPreferences ফাইল নাম সহ সরল ফ্ল্যাট কাঠামো ব্যবহার করে।
না, NSUserDefaults ডেটা এনক্রিপশন ছাড়াই প্লেইন টেক্সটে সংরক্ষণ করে। পাসওয়ার্ড, টোকেন এবং এনক্রিপশন কী-র জন্য Keychain ব্যবহার করুন যা Secure Enclave স্তরে ডেটা এনক্রিপ্ট করে। Keychain সিক্রেট পড়ার আগে বায়োমেট্রিক অথেনটিকেশন (Face ID / Touch ID) এর মতো অ্যাক্সেস অ্যাট্রিবিউটও সমর্থন করে।
একই ব্যবহারকারীর ডিভাইসগুলির মধ্যে সিঙ্ক করার জন্য NSUbiquitousKeyValueStore — iCloud ক্লাউড কী-ভ্যালু স্টোরেজ ব্যবহার করুন। একটি ডিভাইসে এই পরিষেবাতে লেখা ডেটা একই iCloud অ্যাকাউন্টের অন্যান্য সমস্ত ডিভাইসে স্বয়ংক্রিয়ভাবে দেখা যায়। সর্বোচ্চ ক্ষমতা: প্রতি অ্যাপ্লিকেশনে 1 MB, 1024 কী।
সমস্ত ডেটা মুছতে, অ্যাপ্লিকেশনের Bundle Identifier সহ removePersistentDomain(forName:) পদ্ধতি কল করুন। পৃথক মান মুছতে removeObject(forKey:) ব্যবহার করুন। সম্পূর্ণ সেটিংস রিসেটের জন্য: UserDefaults.standard.removePersistentDomain(forName: Bundle.main.bundleIdentifier!)। সমস্ত মুছে ফেলা তাৎক্ষণিকভাবে ইন-মেমরি ক্যাশে প্রয়োগ করা হয়।
Apple NSUserDefaults-এর আকারের উপর কঠোর সীমা নির্ধারণ করে না, কিন্তু সমস্ত সংরক্ষিত ডেটার মোট ভলিউম 100 KB-এর বেশি না করার পরামর্শ দেওয়া হয়। বড় ভলিউমের জন্য CoreData বা FileManager ব্যবহার করুন। 1 MB-এর বেশি ডেটা সংরক্ষণ করলে, অ্যাপ্লিকেশন লঞ্চের সময় পড়ার কর্মক্ষমতা লক্ষণীয়ভাবে হ্রাস পেতে পারে।
সারসংক্ষেপ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন