Ios SwiftUI中的Mockable@AppStorage

Ios SwiftUI中的Mockable@AppStorage,ios,swift,swiftui,mocking,Ios,Swift,Swiftui,Mocking,在开发UIKit应用程序时,通过定义协议并在UIViewController中注入所需的实现,很容易模拟UserDefaults protocol Defaults { var numberOfHandsPlayed: Int { get set } } struct AppDefaults: Defaults { static let shared = AppDefaults() private let userDefaults = UserDefaults.stan

在开发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