Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift: Is there any way to use @AppStorage with @Observable?

I‘d like to store my user defaults in a class. With the old Swift data flow it was possible to use it in a class. Now, with the new system (Xcode 15, Beta 2), it doesn’t work anymore. Is there any way to use it? Maybe a workaround?

This is how it worked before:

import SwiftUI

class UserInfo: ObservableObject {

@AppStorage("username") var username: String = ""

}

And now I want to use the new system:

import SwiftUI

@Observable class UserInfo {

@AppStorage("username") var username: String = ""

}

Unfortunately, it doesn’t work.

like image 890
scotland1912 Avatar asked Aug 31 '25 03:08

scotland1912


2 Answers

This is the way while @AppStorage is incompatible with @Observable.

@Observable
final class SomeClass {
    var name: String {
        get {
            access(keyPath: \.name)
            return UserDefaults.standard.string(forKey: "name") ?? ""
        }
        set {
            withMutation(keyPath: \.name) {
                UserDefaults.standard.setValue(newValue, forKey: "name")
            }
        }
    }
}

Code from Swift Forums.

like image 55
JS1010111 Avatar answered Sep 02 '25 19:09

JS1010111


Other answers in this post cover, pretty much, all the real uses, but, for the sake of completeness, here’s a variant that uses the @AppStorage macro:

@Observable
class MyModel {
    
    // Externally visible properties
    
    @ObservationIgnored
    var name: String {
        get {
            access(keyPath: \.name)
            return _name
        }
        set {
            withMutation(keyPath: \.name) {
                _name = newValue
            }
        }
    }
    
    // Internal stored properties
    
    @ObservationIgnored
    @AppStorage("name")
    private var _name: String = "Bob"
    
}

Quite verbose, but doesn’t use any external macros and quite easy to extend it to support, say, storing Codable.

like image 26
Baglan Avatar answered Sep 02 '25 19:09

Baglan