What it is
A Kotlin Multiplatform key-value storage library wrapping SharedPreferences on Android, NSUserDefaults on Apple platforms and equivalents elsewhere.
Settings exposes typed get and put methods. Platform-specific construction happens once, behind expect/actual, and shared code uses the interface.
Installation
implementation("com.russhwolf:multiplatform-settings:1.2.0")Getting started
The smallest useful thing you can do with it, and what each part means.
kotlin
// commonMain
expect fun createSettings(): Settings
class Preferences(private val settings: Settings) {
var theme: String
get() = settings.getString("theme", "system")
set(value) = settings.putString("theme", value)
var onboarded: Boolean
get() = settings.getBoolean("onboarded", false)
set(value) = settings.putBoolean("onboarded", value)
}
// androidMain
actual fun createSettings(): Settings =
SharedPreferencesSettings(context.getSharedPreferences("app", MODE_PRIVATE))
// iosMain
actual fun createSettings(): Settings = NSUserDefaultsSettings(NSUserDefaults.standardUserDefaults)Advanced usage
Where the library earns its place over a simpler alternative.
kotlin
class Preferences(settings: Settings) {
// Property delegates remove the getter/setter boilerplate.
var theme: String by settings.string("theme", defaultValue = "system")
var fontScale: Float by settings.float("font_scale", 1.0f)
var lastSync: Long? by settings.nullableLong("last_sync")
}
// Observe as a Flow (requires the coroutines artifact and an
// ObservableSettings implementation).
@OptIn(ExperimentalSettingsApi::class)
val themeFlow: Flow<String> =
(settings as ObservableSettings).getStringFlow("theme", "system")Errors and fixes
The failures you are most likely to hit, and what actually resolves them.
- Values do not persist on iOS
- NSUserDefaults writes asynchronously. It is normally fine, but call synchronize() before an expected termination in tests.
- Flow APIs will not compile
- They are experimental and need @OptIn(ExperimentalSettingsApi::class) plus the coroutines artifact.
Best practices
- Wrap Settings in a typed class rather than scattering string keys through the codebase.
- Use property delegates to remove getter and setter boilerplate.
- Store only small values; use SQLDelight or a file for anything larger.
- Never store secrets here — use the platform keychain or EncryptedSharedPreferences.
Background
Why it exists, and what it was reacting to.
Every platform has its own small-preferences API with a different name. This library gives shared code one interface so settings logic need not be written per target.
