在开发UIKit应用程序时,通过定义协议并在UIViewController
中注入所需的实现来模拟UserDefaults
非常容易。
protocol Defaults {
var numberOfHandsPlayed: Int { get set }
}
struct AppDefaults: Defaults {
static let shared = AppDefaults()
private let userDefaults = UserDefaults.standard
struct Keys {
private init() {}
static let numberOfHandsPlayed = "numberOfHandsPlayed"
}
var numberOfHandsPlayed: Int {
get {
userDefaults.integer(forKey: Keys.numberOfHandsPlayed)
}
set(numberOfHandsPlayed) {
userDefaults.setValue(numberOfHandsPlayed, forKey: Keys.numberOfHandsPlayed)
}
}
}
struct MockDefaults: Defaults {
var numberOfHandsPlayed: Int {
get {
// mocking behaviour
}
set(numberOfHandsPlayed) {
// mocking behaviour
}
}
class PracticeViewController: UIViewController {
private var defaults: Defaults?
// defaults can be set to MockDefaults or AppDefaults
}
但现在使用SwiftUI,我可以使用@AppStorage
属性包装器执行以下操作:
@AppStorage("numberOfHandsPlayed") var numberOfHandsPlayed: Int = 3
SwiftUI中是否有一个干净的解决方案来模拟这个属性包装器,并具有与我的UIKit示例中相同的灵活性?
AppStorage
允许指定要使用的存储(默认为标准UserDefaults
(,因此此功能可用于您的目的。
一种可能的方法是对标准用户默认值进行子类化,并在以后需要时对其进行模拟。
class MyUserDefaults: UserDefaults {
// override/add anything needed here
}
struct DemoView: View {
@AppStorage("numberOfHandsPlayed", store: MyUserDefaults()) var numberOfHandsPlayed: Int = 3
// ... other code