ala*_*dey 9 uilabel swift swiftui
我想在按下文本标签后更新它,但在我的应用程序运行时收到此错误(没有编译错误):[SwiftUI] 在视图更新期间修改状态,这将导致未定义的行为。
这是我的代码:
import SwiftUI
var randomNum = Int.random(in: 0 ..< 230)
struct Flashcard : View {
@State var cardText = String()
var body: some View {
randomNum = Int.random(in: 0 ..< 230)
cardText = myArray[randomNum].kana
let stack = VStack {
Text(cardText)
.color(.red)
.bold()
.font(.title)
.tapAction {
self.flipCard()
}
}
return stack
}
func flipCard() {
cardText = myArray[randomNum].romaji
}
}
Run Code Online (Sandbox Code Playgroud)
Sco*_*ter 13
View如果您在不返回 a (因此无法使用或 手势)的函数中遇到此问题onAppear,另一种解决方法是将更新包装在异步更新中:
func updateUIView(_ uiView: ARView, context: Context) {
if fooVariable { do a thing }
DispatchQueue.main.async { fooVariable = nil }
}
Run Code Online (Sandbox Code Playgroud)
不过,我无法判断这是否是最佳实践。
编辑:我现在在苹果工作;这是一个可以接受的方法。另一种方法是使用符合ObservableObject.
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"
}
}
}
Run Code Online (Sandbox Code Playgroud)
在这里,我正在修改@State视图主体内的变量body。问题在于@State变量的突变会导致视图更新,进而调用body视图上的方法。因此,在对 的呼叫进行到一半时body,又发起了对 的另一个呼叫body。这种情况可能会一直持续下去。
另一方面,@State变量可以在onTapGestureblock中发生变化,因为它是异步的,并且直到更新完成后才会被调用。
例如,假设我想在用户每次点击文本视图时更改文本。我可以有一个@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.
}
}
}
Run Code Online (Sandbox Code Playgroud)
对于您的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
Run Code Online (Sandbox Code Playgroud)
但是,如果您希望视图在自身更改时card也更改(并不是说您必须将其作为逻辑下一步执行),那么此代码是不够的。除了弄清楚突变如何以及在何处发生之外,您还需要导入Combine并重新配置card变量和类型本身。Card这是一个不同的问题。
长话短说:修改@State手势块内的变量。如果您想在视图本身之外修改它们,那么除了@State注释之外您还需要其他东西。@State仅供本地/私人使用。
(我使用的是 Xcode 11 beta 5)
每次重绘时(如果状态变量发生变化)var body: some View都会重新评估。在您的情况下这样做会更改另一个状态变量,这将在没有缓解的情况下结束循环,因为每次重新评估时都会进行另一个状态变量更改。
SwiftUI 如何处理这个问题既不能保证稳定,也不能保证安全。这就是为什么 SwiftUI 警告您下次可能会因此崩溃。
无论是由于实现更改、突然触发边缘条件,还是在从同一变量读取文本时异步更改文本时运气不佳,都会给您带来垃圾字符串/崩溃。
在大多数情况下,你可能会没事,但这比平常更不那么有保证。
| 归档时间: |
|
| 查看次数: |
12774 次 |
| 最近记录: |