NSUserDefaults — шта је то, UserDefaults API и рад са подешавањима iOS

Аутор: IT Sectr Објављено: 2026-03-12 Време читања: 10 мин

NSUserDefaults је складиште података кључ-вредност у iOS, watchOS, tvOS и macOS, намењено чувању подешавања и конфигурација апликације. Подаци се чувају у plist фајлу у пешчанику апликације и аутоматски се синхронизују са iCloud путем NSUbiquitousKeyValueStore. Према званичној документацији Apple Developer, 2025, NSUserDefaults подржава чување примитивних типова: String, Int, Bool, Float, Double, Data, Date, Array и Dictionary. Класа је преименована у UserDefaults од Swift 3, али њено Objective-C име NSUserDefaults остаје широко коришћено у коду и Apple документацији.

Главно

  • NSUserDefaults — складиште кључ-вредност на iOS и macOS за чување једноставних подешавања апликације у plist фајлу.
  • Подржава девет типова података: String, Int, Bool, Float, Double, Data, Date, Array и Dictionary.
  • Подаци се аутоматски синхронизују са iCloud путем NSUbiquitousKeyValueStore уз подршку програмера.
  • Користи систем регистара (домена) са каскадним претраживањем вредности по ланцу домена.
  • За чување осетљивих података Apple препоручује коришћење Keychain уместо NSUserDefaults.

Шта је NSUserDefaults?

NSUserDefaults (UserDefaults у Swift) је уграђени Apple механизам за чување парова кључ-вредност у plist формату. Доступан је на свим Apple платформама: iOS, iPadOS, watchOS, tvOS и macOS. Основна намена — чување корисничких преференци, стања интерфејса, first-launch заставица, изабраних опција и других једноставних података који преживљавају поновно покретање апликације.

Свака iOS апликација има изоловани пешчаник, а NSUserDefaults се чува у директоријуму Library/Preferences унутар овог пешчаника у фајлу са именом Bundle Identifier. plist фајл садржи парове кључ-вредност, где је кључ стринг, а вредност један од подржаних типова. Величина фајла није ограничена, али Apple препоручује чување само подешавања у UserDefaults, а не великих количина података.

Од iOS 8, NSUserDefaults подржава App Groups — заједничко складиште између апликација истог програмера и њихових проширења (виџети, watchOS пратеће апликације). За то се користи иницијализатор init?(suiteName:) са идентификатором App Group. Ово омогућава, на пример, виџету на Today екрану да чита подешавања из главне апликације без дуплирања логике чувања.

Формат чувања: plist на уређају

Физички, NSUserDefaults се чува у бинарном plist фајлу на путањи: {Sandbox}/Library/Preferences/com.example.myapp.plist. Фајл користи бинарни plist формат (NSPropertyListBinaryFormat_v1_0) за компактност и брзину читања. На macOS-у, фајл може бити у XML формату ради компатибилности. За разлику од SharedPreferences на Android-у, plist фајлови UserDefaults-а могу садржати угнежђене структуре путем Dictionary и Array.

Фајлови NSUserDefaults нису подразумевано шифровани. Подаци се чувају у отвореном облику и могу се прочитати при物理чком приступу уређају или кроз резервну копију. За чување осетљивих података (лозинке, токени, кључеви за шифровање) Apple категорички препоручује коришћење Keychain, који аутоматски шифрује податке на нивоу оперативног система.

Како ради NSUserDefaults у iOS

NSUserDefaults ради на принципу кеширања у меморији са периодичном синхронизацијом на диск. При првом обраћању стандардној инстанци UserDefaults.standard, систем учитава plist фајл у RAM меморију у облику Dictionary. Сва накнадна читања се обављају из меморије. Писање се такође прво врши у меморији, а синхронизација на диск се одвија периодично у позадини.

Операције писања користе метод set(_:forKey:), који прихвата вредност опционог типа Any?. Вредност може бити nil — за уклањање кључа. За тренутно писање на диск раније се користио метод synchronize(), али од iOS 7 и OS X 10.9 више није потребан — систем аутоматски синхронизује податке у редовним интервалима. Apple је званично прогласио synchronize() сувишним у својој документацији.

Регистри UserDefaults-а и домени

NSUserDefaults користи систем регистара (домена) за организовање претраге вредности. Када апликација затражи вредност по кључу, UserDefaults узастопно проверава домене одређеним редоследом: прво NSArgumentDomain (аргументи командне линије), затим домен апликације (Application), потом NSGlobalDomain (системска подешавања), затим домене специфичне за језик и на крају NSRegistrationDomain (подразумеване вредности регистроване путем register(defaults:)).

swift
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 је програмски домен који постоји само у RAM меморији и не чува се на диску. Користи се за постављање подразумеваних вредности које су активне док апликација не запише своју вредност у домен апликације. Ово омогућава стварање јединствене тачке конфигурације подразумеваних подешавања која се могу централизовано мењати у фази развоја.

Главне методе NSUserDefaults

NSUserDefaults пружа скуп типизованих метода за читање и писање података: string(forKey:), integer(forKey:), bool(forKey:), float(forKey:), double(forKey:), data(forKey:), array(forKey:), dictionary(forKey:) и object(forKey:). Свака метода читања има одговарајућу методу писања set(_:forKey:) са аутоматским одређивањем типа чуване вредности. Swift верзија UserDefaults-а користи строгу типизцију, али Objective-C верзија прихвата и враћа id.

Метод читања (Swift)Тип податакаПодразумевана вредност
string(forKey:)String?nil
integer(forKey:)Int0
bool(forKey:)Boolfalse
float(forKey:)Float0.0
double(forKey:)Double0.0
data(forKey:)Data?nil

synchronize и његова актуелност

Метод synchronize() у NSUserDefaults присилно уписује све измене из меморије на диск. У раним верзијама iOS-а овај метод је било потребно позвати након сваког писања ради гаранције чувања података. Од iOS 7, систем аутоматски синхронизује UserDefaults у позадини, а Apple је званично прогласио synchronize() сувишним. Позивање овог метода не изазива грешку, али не даје никакве додатне гаранције чувања.

За праћење измена, NSUserDefaults пружа обавештење UserDefaults.didChangeNotification и KVO метод посматрања addObserver(_:forKeyPath:options:context:). У SwiftUI-ју је доступан Property Wrapper @AppStorage, који аутоматски синхронизује вредност у UserDefaults-у са ажурирањем UI. @AppStorage подржава исте типове као UserDefaults и представља пожељан начин рада са подешавањима у SwiftUI апликацијама.

swift
// Праћење промена путем 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 (заједничко складиште између апликације и проширења) користи се иницијализатор UserDefaults(suiteName:) са идентификатором App Group. На пример, "group.com.example.myapp". Подаци записани у ову инстанцу доступни су из главне апликације, виџета, watchOS пратеће апликације и других проширења која припадају истој App Group. Свака suite инстанца чува се у посебном plist фајлу.

NSUserDefaults vs алтернативе чувања

Упркос удобности и једноставности, NSUserDefaults није универзално складиште за све типове података на iOS-у. У зависности од обима, критичности и безбедносних захтева, Apple пружа неколико алтернатива, од којих је свака оптимизована за одређени сценариј коришћења.

РешењеКада користитиОграничења
NSUserDefaultsПодешавања интерфејса и конфигурацијаНије погодно за велике податке и тајне
KeychainЛозинке, токени, кључеви за шифровањеСложеније за коришћење, спорије
CoreDataСтруктурирани подаци са везамаПреобимно за 10-20 подешавања
FileManagerДокументи, слике, бинарни подациЗахтева ручно управљање фајловима
CloudKitОблачна синхронизација између уређајаЗахтева iCloud налог и мрежну везу

Keychain — безбедно чување

Keychain је заштићено Apple складиште за поверљиве податке. За разлику од NSUserDefaults-а, сви подаци у Keychain-у су шифровани на нивоу оперативног система коришћењем хардверског шифровања Secure Enclave на компатибилним уређајима. Keychain се аутоматски закључава и откључава заједно са уређајем и подржава поделу приступа између апликација истог програмера путем Keychain Access Groups.

Главни недостатак Keychain — сложеност API-ја. За једноставно чување стринга потребно је креирати захтев SecItemAdd са навођењем атрибута: класе (kSecClassGenericPassword), сервиса (kSecAttrService), налога (kSecAttrAccount) и самих података (kSecValueData). За поједностављење рада са Keychain-ом постоје спољни омоти, као што су KeychainAccess и SwiftKeychainWrapper, који пружају згодан интерфејс кључ-вредност сличан UserDefaults-у.

Пример коришћења NSUserDefaults у Swift

Размотримо практичан пример: чување и враћање стања онбординга (екрана добродошлице) у iOS апликацији коришћењем NSUserDefaults. При првом покретању корисник види екране онбординга, након чијег проласка се заставица чува у UserDefaults-у. При наредним покретањима онбординг се прескаче. За SwiftUI се користи @AppStorage, за UIKit — директан приступ UserDefaults.standard.

Чување стања онбординга

Направимо менаџер OnboardingManager који инкапсулира рад са UserDefaults-ом за чување статуса онбординга. Менаџер пружа својство isOnboardingCompleted за проверу стања и метод markOnboardingCompleted за постављање заставице. Кључ за чување је издвојен у константу ради спречавања грешака у куцању. За јединично тестирање, менаџер користи протокол UserDefaultsProtocol, што омогућава замену правог складишта на MockUserDefaults.

swift
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. Објекат се серијализује у Data путем JSONEncoder-а, чува путем set(_:forKey:), а при читању десеријализује из Data назад у објекат путем JSONDecoder-а. Овај приступ омогућава чување сложених структура у UserDefaults-у без губитка типске безбедности.

swift
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 препоручује ограничавање величине чуваних података на неколико десетина килобајта. За чување великих објеката (слика, докумената, серијализованих модела) треба користити FileManager са Documents директоријумом или CoreData. Поред тога, UserDefaults не подржава верзионисање шеме података — при промени структуре Codable модела, стари подаци се можда неће десеријализовати, и то треба обрадити у коду апликације.

Често постављана питања

По чему се NSUserDefaults разликује од SharedPreferences на Android-у?

Оба су складишта кључ-вредност, али NSUserDefaults подржава више типова (Data, Date, Array, Dictionary) и аутоматски се синхронизује са iCloud. SharedPreferences чува податке у XML-у, NSUserDefaults — у plist формату. NSUserDefaults има систем домена са каскадним претраживањем, SharedPreferences користи једноставну равну структуру са именима фајлова.

Да ли је безбедно чувати лозинке у NSUserDefaults?

Не, NSUserDefaults чува податке у отвореном облику без шифровања. За лозинке, токене и кључеве за шифровање користите Keychain, који шифрује податке на нивоу Secure Enclave. Keychain такође подржава атрибуте приступа попут биометријске аутентификације (Face ID / Touch ID) пре читања тајне.

Како синхронизовати NSUserDefaults између уређаја?

За синхронизацију између уређаја истог корисника користите NSUbiquitousKeyValueStore — облачно складиште кључ-вредност iCloud-а. Подаци записани у овај сервис на једном уређају аутоматски се појављују на свим другим уређајима истог iCloud налога. Максимални обим — 1 MB по апликацији, 1024 кључа.

Како избрисати све податке из NSUserDefaults?

За брисање свих података позовите метод removePersistentDomain(forName:) са Bundle Identifier-ом апликације. За брисање појединачних вредности користите removeObject(forKey:). За потпуни ресет подешавања апликације: UserDefaults.standard.removePersistentDomain(forName: Bundle.main.bundleIdentifier!). Сва брисања се одмах примењују на кеш у меморији.

Која је максимална величина података у NSUserDefaults?

Apple не поставља строгу границу за величину NSUserDefaults, али се препоручује да не прелази 100 KB укупног обима свих чуваних података. За веће обиме користите CoreData или FileManager. При чувању преко 1 MB података, перформансе читања при покретању апликације могу приметно опасти.

Резиме

  • NSUserDefaults — уграђено Apple складиште кључ-вредност за једноставна подешавања апликације у plist формату.
  • Подржава девет типова података: String, Int, Bool, Float, Double, Data, Date, Array и Dictionary.
  • Користи систем домена са каскадним претраживањем кроз NSRegistrationDomain, NSGlobalDomain и домен апликације.
  • За синхронизацију између уређаја Apple пружа NSUbiquitousKeyValueStore са лимитом од 1 MB по апликацији.
  • За безбедност користите Keychain за лозинке и токене, а не NSUserDefaults.
  • У SwiftUI пожељан начин рада — Property Wrapper @AppStorage са аутоматском синхронизацијом UI.
  • За велике или структуриране податке бирајте CoreData или FileManager уместо NSUserDefaults.

Развићемо мобилну апликацију под кључ

IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.

Разговарајте о пројекту

Прочитајте такође