struct ContentView: View {
@State var settingsConfiguration: Settings
struct Settings {
var passwordLength: Double = 20
var moreSpecialCharacters: Bool = false
var specialCharacters: Bool = false
var lowercaseLetters: Bool = true
var uppercaseLetters: Bool = true
var numbers: Bool = true
var space: Bool = false
}
var body: some View {
VStack {
HStack {
Text("Password Length: \(Int(settingsConfiguration.passwordLength))")
Spacer()
Slider(value: $settingsConfiguration.passwordLength, from: 1, through: 512)
}
Toggle(isOn: $settingsConfiguration.moreSpecialCharacters) {
Text("More Special Characters")
}
Toggle(isOn: $settingsConfiguration.specialCharacters) {
Text("Special Characters")
}
Toggle(isOn: $settingsConfiguration.space) {
Text("Spaces")
}
Toggle(isOn: $settingsConfiguration.lowercaseLetters) {
Text("Lowercase Letters")
}
Toggle(isOn: $settingsConfiguration.uppercaseLetters) {
Text("Uppercase Letters")
}
Toggle(isOn: $settingsConfiguration.numbers) {
Text("Numbers")
}
Spacer()
}
.padding(.all)
.frame(width: 500, height: 500)
}
}
だから私はここにこのすべてのコードを持っており、スイッチが変更されたときやスライダーがスライドされたときに設定を保存し、アプリの起動時にこのすべてのデータを取得するためにUserDefaultsを使用したいのですが、SwiftUIでUserDefaultsを使用する方法がわかりません(または一般にUserDefaults、私はそれを調べ始めたばかりなので、SwiftUIアプリで使用できますが、表示されるすべての例はUIKitのためのものであり、SwiftUIでそれらを実装しようとすると、大量のエラーが発生します)。
Caramからのアプローチは一般的に大丈夫ですが、コードに非常に多くの問題があるため、SmushyTacoはそれを機能させませんでした。怒鳴るあなたは「箱から出して」実用的な解決策を見つけるでしょう。
import Foundation
import Combine
@propertyWrapper
struct UserDefault<T> {
let key: String
let defaultValue: T
init(_ key: String, defaultValue: T) {
self.key = key
self.defaultValue = defaultValue
}
var wrappedValue: T {
get {
return UserDefaults.standard.object(forKey: key) as? T ?? defaultValue
}
set {
UserDefaults.standard.set(newValue, forKey: key)
}
}
}
final class UserSettings: ObservableObject {
let objectWillChange = PassthroughSubject<Void, Never>()
@UserDefault("ShowOnStart", defaultValue: true)
var showOnStart: Bool {
willSet {
objectWillChange.send()
}
}
}
struct ContentView: View {
@ObservedObject var settings = UserSettings()
var body: some View {
VStack {
Toggle(isOn: $settings.showOnStart) {
Text("Show welcome text")
}
if settings.showOnStart{
Text("Welcome")
}
}
}
以下のコードは、Mohammad Azamの優れたソリューションを このビデオ に適合させています。
import SwiftUI
struct ContentView: View {
@ObservedObject var userDefaultsManager = UserDefaultsManager()
var body: some View {
VStack {
Toggle(isOn: self.$userDefaultsManager.firstToggle) {
Text("First Toggle")
}
Toggle(isOn: self.$userDefaultsManager.secondToggle) {
Text("Second Toggle")
}
}
}
}
class UserDefaultsManager: ObservableObject {
@Published var firstToggle: Bool = UserDefaults.standard.bool(forKey: "firstToggle") {
didSet { UserDefaults.standard.set(self.firstToggle, forKey: "firstToggle") }
}
@Published var secondToggle: Bool = UserDefaults.standard.bool(forKey: "secondToggle") {
didSet { UserDefaults.standard.set(self.secondToggle, forKey: "secondToggle") }
}
}
まず、設定クラスとUserDefaultsの間のリンクを簡単に作成できるようにするプロパティラッパーを作成します。
import Foundation
@propertyWrapper
struct UserDefault<Value: Codable> {
let key: String
let defaultValue: Value
var value: Value {
get {
let data = UserDefaults.standard.data(forKey: key)
let value = data.flatMap { try? JSONDecoder().decode(Value.self, from: $0) }
return value ?? defaultValue
}
set {
let data = try? JSONEncoder().encode(newValue)
UserDefaults.standard.set(data, forKey: key)
}
}
}
次に、設定を保持するデータストアを作成します。
import Combine
import SwiftUI
final class DataStore: BindableObject {
let didChange = PassthroughSubject<DataStore, Never>()
@UserDefault(key: "Settings", defaultValue: [])
var settings: [Settings] {
didSet {
didChange.send(self)
}
}
}
次に、ビューで設定にアクセスします。
import SwiftUI
struct SettingsView : View {
@EnvironmentObject var dataStore: DataStore
var body: some View {
Toggle(isOn: $settings.space) {
Text("\(settings.space)")
}
}
}