SwiftUI:为什么 @AppStorage 的工作方式与我的自定义绑定不同?
SwiftUI: Why does @AppStorage work differently to my custom binding?
我有一个模式 Sheet
,它应该基于 UserDefault
布尔值显示。
我写了一个 UI-Test 来消除 sheet 并且我使用启动参数来控制默认值。
然而,当我最初尝试使用 @AppStorage
时,它似乎并没有保留该值,或者是偷偷地不写它?我的测试失败了,因为在 'dismissing' 模式弹出后,值没有改变。
为了解决这个问题,我编写了一个自定义绑定。但我不确定这两种实现之间的行为差异是什么?这样测试就通过了。
有人知道我不明白什么吗?
干杯!
简单示例
1. AppStorage
struct ContentView: View {
@AppStorage("should.show.sheet") private var binding: Bool = true
var body: some View {
Text("Content View")
.sheet(isPresented: $binding) {
Text("Sheet")
}
}
}
2。自定义绑定:
struct ContentView: View {
var body: some View {
let binding = Binding<Bool> {
UserDefaults.standard.bool(forKey: "should.show.sheet")
} set: {
UserDefaults.standard.set([=11=], forKey: "should.show.sheet")
}
Text("Content View")
.sheet(isPresented: binding) {
Text("Sheet")
}
}
}
测试用例:
final class SheetUITests: XCTestCase {
override func setUpWithError() throws {
continueAfterFailure = false
}
func testDismiss() {
// Given 'true' userdefault value to show sheet on launch
let app = XCUIApplication()
app.launchArguments += ["-should.show.sheet", "<true/>"]
app.launch()
// When the user dismisses the modal view
app.swipeDown()
// Wait a second for animation (make sure it doesn't pop back)
sleep(1)
// Then the sheet should not be displayed
XCTAssertFalse(app.staticTexts["Sheet"].exists)
}
}
即使 运行 应用程序也不起作用,因为那个“.”在键名中(看起来这是 AppStorage 的限制,所以使用简单的符号,如 isSheet
.
IMO test-case 不正确,因为它通过参数域覆盖默认值,但它是 read-only,因此尝试写入持久域,但可能存在那里有相同的值,因此不会生成更改(读取 didSet
)事件,因此 UI.
中没有更新
要对此进行测试,它应该是 inside 应用程序的配对事件,即。一个给出 AppStorage
值 true,另一个给出 false
*注意:布尔值在参数中显示为 0/1(不是 XML),即 -isSheet 1
我有一个模式 Sheet
,它应该基于 UserDefault
布尔值显示。
我写了一个 UI-Test 来消除 sheet 并且我使用启动参数来控制默认值。
然而,当我最初尝试使用 @AppStorage
时,它似乎并没有保留该值,或者是偷偷地不写它?我的测试失败了,因为在 'dismissing' 模式弹出后,值没有改变。
为了解决这个问题,我编写了一个自定义绑定。但我不确定这两种实现之间的行为差异是什么?这样测试就通过了。
有人知道我不明白什么吗?
干杯!
简单示例
1. AppStorage
struct ContentView: View {
@AppStorage("should.show.sheet") private var binding: Bool = true
var body: some View {
Text("Content View")
.sheet(isPresented: $binding) {
Text("Sheet")
}
}
}
2。自定义绑定:
struct ContentView: View {
var body: some View {
let binding = Binding<Bool> {
UserDefaults.standard.bool(forKey: "should.show.sheet")
} set: {
UserDefaults.standard.set([=11=], forKey: "should.show.sheet")
}
Text("Content View")
.sheet(isPresented: binding) {
Text("Sheet")
}
}
}
测试用例:
final class SheetUITests: XCTestCase {
override func setUpWithError() throws {
continueAfterFailure = false
}
func testDismiss() {
// Given 'true' userdefault value to show sheet on launch
let app = XCUIApplication()
app.launchArguments += ["-should.show.sheet", "<true/>"]
app.launch()
// When the user dismisses the modal view
app.swipeDown()
// Wait a second for animation (make sure it doesn't pop back)
sleep(1)
// Then the sheet should not be displayed
XCTAssertFalse(app.staticTexts["Sheet"].exists)
}
}
即使 运行 应用程序也不起作用,因为那个“.”在键名中(看起来这是 AppStorage 的限制,所以使用简单的符号,如
isSheet
.IMO test-case 不正确,因为它通过参数域覆盖默认值,但它是 read-only,因此尝试写入持久域,但可能存在那里有相同的值,因此不会生成更改(读取
中没有更新didSet
)事件,因此 UI.要对此进行测试,它应该是 inside 应用程序的配对事件,即。一个给出
AppStorage
值 true,另一个给出 false
*注意:布尔值在参数中显示为 0/1(不是 XML),即 -isSheet 1