我遇到一种情况,要求用户记住字符串数组。在提示您从数组中随机选择一个元素时,要求用户命名三个相邻元素。 (在现实生活中,这全都与音符有关-为简单起见,我将问题归结为字符串和数组)。有两个并发症。首先,代码应避免连续两次向用户显示相同的提示元素。其次,用户可以随时在命名在提示元素之前显示的元素或在提示元素之后显示的元素(在音乐上,这对应于递增比例或递减比例)之间进行切换。
StringChooser
结构包含字符串数组,并提供了返回随机选择的字符串的功能。它还可以保存随机选择的字符串的索引,以便以后可以使用该索引查找相邻的元素。
struct StringChooser {
// MARK: API
var myStrings: [ String ]
var lastChosenStringIndex = Int.max
// MARK: Methods
mutating func getRandomString() -> String {
// pick random string that is NOT the same as previously
// picked element
var randomIndex: Int
repeat {
randomIndex = Int.random(in: 0 ..< myStrings.count )
} while randomIndex == lastChosenStringIndex
// save the index for the picked element so that
// later we can find the adjacent elements
lastChosenStringIndex = randomIndex // supposed SAVE!
return myStrings[ randomIndex ]
}
}
在初始化StringChooser结构期间会出现问题。 ContentView
结构(如下所示)对此进行了说明。它包括一个Text子视图,以显示从数组中随机选择的元素;第二个Text子视图,以显示随机选择的元素的索引号。第一部分工作。每次显示视图时,都会随机选择一个新字符串。但是,第二部分失败。由于某种原因,索引除了在结构中分配给索引的初始值(即Int.max)外,别无其他。我不明白为什么元素的随机选择有效,但是没有相应索引的记录。非常感谢您对这种(似乎)差异的想法。
struct ContentView: View {
@Binding var stringChooser: StringChooser
@State private var chosenString = "not initialized"
var body: some View {
VStack {
Spacer()
Text( "Random String: \( stringChooser.getRandomString() )." )
Spacer()
Text("Index of chosen string: '\( stringChooser.lastChosenStringIndex )'.")
Spacer()
Button( "Again" )
{
chosenString =
stringChooser.getRandomString()
}
Spacer()
}
}
}
[其他方法:如果我尝试使用init()初始化StringChooser实例,则会产生相同的结果。在模拟器中运行时,这会引起运行时警告,该警告指出在View外部更改State变量可能会导致问题。]