SwiftUI provides two approaches for storing small amount of data. It's a convenient way to store user's settings (@AppStorage
) or value of text field between restarts (@SceneStorage
).
AppStorage
The @AppStorage
property wrapper can store data that is accessible throughout the entire app.
AppStorage uses UserDefaults as it backend and can store default user preferences (language preferences, color theme, etc).
To work properly @AppStorage
requires a string as a key for inner storage
@AppStorage("theme") var theme: String = "bright"
SceneStorage
Alongside AppStorage
, SwiftUI also offers a @SceneStorage
attribute that works the same as @AppStorage
, except that the persisted storage is limited to a scene instead of being app-wide.
@SceneStorage("about") var about: String = ""
Next, we can use it in conjunction with a TextEditor
as follows
var body: some View { TextEditor(text: $about).padding() }
This will ensure that any text entered into the text field is stored within the scene between app restarts.
Storing custom type
The @AppStorage
and @SceneStorage
can store only primitive types like Bool, Int, Double, String, URL and Data. All other types must be encoded in Data
object and conforms to the Codable
protocol.
Consider the following struct
struct Movie: Codable { var title: String var year: Int } var cinema = Movie(title: "The Godfather", year: 1972)
The following example uses a JSON encoder to encode cinema
instance and store it using the @AppStorage
.
@AppStorage("cinema") var cinemaStore: Data = Data() let encoder = JSONEncoder() if let data = try? encoder.encode(cinema) { cinemaStore = data }
To retrieve the data from storage use following snippet
let decoder = JSONDecoder() if let movie = try? decoder.decode(Movie.self, from: cinemaStore) { cinema = movie }