struct ContentView: View {
@State var cardText: String = "Hello"
var body: some View {
self.cardText = "Goodbye" // <<< This mutation is no good.
return Text(cardText)
.onTapGesture {
self.cardText = "World"
}
}
}
在这里,我正在修改 body 视图主体中的 @State 变量。问题是对@State 变量的突变会导致视图更新,进而在视图上调用body 方法。因此,已经在对body 的调用中,发起了对body 的另一个调用。这可能会一直持续下去。
另一方面,@State 变量可以在onTapGesture 块中进行变异,因为它是异步的,直到更新后才会被调用结束了。
例如,假设我想在用户每次点击文本视图时更改文本。我可以有一个@State 变量isFlipped,当点击文本视图时,手势块中的代码会切换isFlipped 变量。 由于它是一个特殊的@State 变量,该更改将驱动视图更新。 由于我们不再处于视图更新的中间,我们不会得到“视图期间的修改状态”更新”警告。
struct ContentView: View {
@State var isFlipped = false
var body: some View {
return Text(isFlipped ? "World" : "Hello")
.onTapGesture {
self.isFlipped.toggle() // <<< This mutation is ok.
}
}
}
对于您的FlashcardView,您可能希望在视图本身之外定义卡片并将其作为参数传递到视图中以进行初始化。
struct Card {
let kana: String
let romaji: String
}
let myCard = Card(
kana: "Hello",
romaji: "World"
)
struct FlashcardView: View {
let card: Card
@State var isFlipped = false
var body: some View {
return Text(isFlipped ? card.romaji : card.kana)
.onTapGesture {
self.isFlipped.toggle()
}
}
}
#if DEBUG
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
return FlashcardView(card: myCard)
}
}
#endif
但是,如果您希望视图在 card 本身发生变化时发生变化(不一定应该这样做是合乎逻辑的下一步),那么这段代码是不够的。您需要导入Combine 并重新配置card 变量和Card 类型本身,此外还要弄清楚突变将如何以及在何处发生。这是一个不同的问题。
长话短说:修改手势块中的@State 变量。如果您想在视图本身之外修改它们,那么除了 @State 注释之外,您还需要其他东西。 @State 仅供本地/私人使用。
(我使用的是 Xcode 11 beta 5)