How can the string from a TextField be stored in UserDefaults using SwiftUI?
I have seen this tutorial on how to save the state of a toggle in UserDefaults and that looks promising, but I can't figure out how to use the same idea for storing the content from a TextField: https://www.youtube.com/watch?v=nV-OdfQhStM&list=PLerlU8xuZ7Fk9zRMuh7JCKy1eOtdxSBut&index=3&t=329s
I still want to be able to update the string by typing new text in the TextField, but unless I do that, I want the string to be maintained in the view. Both when changing page and completely exitting the app.
For things like these I suggest you use the .debounce
publisher.
import SwiftUI
import Combine
class TestViewModel : ObservableObject {
private static let userDefaultTextKey = "textKey"
@Published var text = UserDefaults.standard.string(forKey: TestViewModel.userDefaultTextKey) ?? ""
private var canc: AnyCancellable!
init() {
canc = $text.debounce(for: 0.2, scheduler: DispatchQueue.main).sink { newText in
UserDefaults.standard.set(newText, forKey: TestViewModel.userDefaultTextKey)
}
}
deinit {
canc.cancel()
}
}
struct ContentView: View {
@ObservedObject var viewModel = TestViewModel()
var body: some View {
TextField("Type something...", text: $viewModel.text)
}
}
The .debounce
publisher documentation says:
Use this operator when you want to wait for a pause in the delivery of events from the upstream publisher. For example, call debounce on the publisher from a text field to only receive elements when the user pauses or stops typing. When they start typing again, the debounce holds event delivery until the next pause.
You don't really want to save the text in the UserDefaults
each time the user types something (i.e. for every character he/she types). You just want the text to be ultimately saved to the UserDefaults. The debounce publisher waits for the user to stop typing according to the time you set in the debounce init (in the example above 0.2 secs) and then forwards the event to the sink
subscriber that actually saves the text. Always use the debounce publisher when you have a lot of events (for example new text typed in a text field) that may trigger "heavy" operations (whatever you can think of: something related to CoreData, network calls and so forth).