Как мне использовать UserDefaults с SwiftUI? - PullRequest
2 голосов
/ 30 июня 2019
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 для сохранения настроек при каждом изменении переключателя или скольжения слайдера и для извлечения всех этих данных при запуске приложения, но я понятия не имею, как бы я это сделалперейти к использованию UserDefaults со SwiftUI (или вообще UserDefaults, я только начал изучать его, чтобы использовать его для своего приложения SwiftUI, но все примеры, которые я вижу, относятся к UIKit, и когда я пытаюсь реализовать их в SwiftUI, я просто сталкиваюсь скуча ошибок).

Ответы [ 2 ]

1 голос
/ 30 июня 2019

Во-первых, создайте оболочку свойства, которая позволит нам легко установить связь между вашим классом настроек и параметрами 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)")
        }
    }
}
0 голосов
/ 14 июля 2019

Подход от caram в целом нормальный, но с кодом так много проблем, что SmushyTaco не работает.Ниже вы найдете рабочее решение «Из коробки».

// 1. Свойство UserDefaultsWrapper

import Foundation

@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)
        }
    }
}

// 2. Класс UserSettings

final class UserSettings: BindableObject {
    let didChange = PassthroughSubject<Void, Never>()

    @UserDefault("ShowOnStart", defaultValue: false)
    var showOnStart: Bool {
        didSet {
            didChange.send()
        }
    }
}

// 3. Представление SwiftUI

struct SettingsView : View {
    @ObjectBinding var settings = UserSettings()

    var body: some View {
        VStack {
            Toggle(isOn: $settings.showOnStart) {
                Text("Show welcome text")
            }
            if settings.showOnStart{
                Text("Welcome")
            }
        }
    }
}
...