防止 SwiftUI 中的数组重新洗牌
Posted
技术标签:
【中文标题】防止 SwiftUI 中的数组重新洗牌【英文标题】:Prevent array re-shuffle in SwiftUI 【发布时间】:2021-09-24 02:49:02 【问题描述】:我一直在 SwiftUI 中创建一个问答应用程序,并一直在尝试为随机排列的答案创建一个数组。最初我将数组改组如下:
var answers = ["answerOne", "answerTwo", "answerThree", "answerfour"].shuffled
这个数组以ForEach
循环的形式显示在屏幕上,该循环在如下所示的列中提供了选项(可以选择的答案):
Question:
Answer One
Answer Two
Answer Three
Answer Four
(Check answer button)
虽然效果很好,但当按下检查答案按钮时,答案数组将再次随机排列为不同的顺序,如下所示,这是不可取的。
Question:
Answer Three
Answer One
Answer Two
Answer Four
(Next question button)
有没有一种方法可以让我只在按下“下一个问题按钮”而不是“检查答案按钮”时才对数组进行洗牌?
以下是我尝试作为解决方案的代码,但它似乎没有奏效,我非常感谢任何人的任何意见或想法!
Button(action:
if(oddEven % 2 == 0)
checkNextText = "Next"
oddEven += 1
else
checkNextText = "Check"
answers.shuffled()
oddEven += 1
注意:checkNextText
是屏幕底部按钮的文本,oddEven
是一个 Int 变量,用于确定按钮应该读取 check 还是 next。
最小复制代码:
import SwiftUI
struct ContentView: View
@State var oddEven = 0
@State var checkNextText = "Check"
var body: some View
var orderedAnswers = [
"answerOne",
"answerTwo",
"answerThree",
"answerFour"
].shuffled()
Text("Question One")
ForEach(0..<4) number in
Button(action: , label:
Text(orderedAnswers[number])
)
Button(action:
if(oddEven % 2 == 0)
checkNextText = "Next"
oddEven += 1
else
checkNextText = "Check"
oddEven += 1
, label:
Text(checkNextText)
)
【问题讨论】:
您能否包含一个minimal reproducible example,以便他人可以复制并粘贴到 Xcode 中以查看您目前拥有的内容? 嗨!没问题,我会在编辑中添加一个。body
会在您的视图中的某些内容发生变化时刷新...所以由于var orderedAnswers = [
在body
内,它会意外地重新洗牌。把它移到外面。
感谢@aheze 的回答。唯一的问题是我提供的代码是实际代码的一个非常精简的版本,将它移到体外需要大量的重构。有没有其他方法可以实现洗牌,而不必将数组移到体外?
@imjonu 不幸的是没有。通常你希望你的所有变量都在身体之外,否则你会遇到奇怪的副作用。
【参考方案1】:
正如其他人所建议的那样,惯用的方法是将数组存储在您的视图中,而不是作为body
属性中的局部变量,因为正如已经指出的那样,每次body
是调用(可能不止一次发生)。
但是,如果由于各种原因无法将代码提取到正文之外,另一种方法是使用仅设置一次的 @State
属性:
struct ContentView: View
@State orderedAnswers: [String]?
,仅当状态未设置时才进行计算:
var body: some View
var orderedAnswers = self.orderedAnswers ?? [
"answerOne",
"answerTwo",
"answerThree",
"answerFour"
].shuffled()
【讨论】:
以上是关于防止 SwiftUI 中的数组重新洗牌的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI 中的 List 是不是复用类似于 UITableView 的单元格?
如何在 Touch Down 实现时防止 SwiftUI 上的重新触发
如何防止 SwiftUI 像使用 @StateObject 一样重新初始化我的包装属性?