SwiftUI:输入特定字母时修改文本颜色,避免重复变色问题
解决SwiftUI中重复字母逐个变色的问题
问题分析
当前代码用typedLetters.contains(letter)判断字母是否变色,导致只要输入过某字母,所有同字母都会同步变色。要实现逐个变色,需要跟踪每个位置的字母是第几次出现,以及该字母已被输入的次数,通过两者的比较来决定是否变色。
修改方案
1. 给数据模型添加字母计数方法
在WordDataModel中扩展一个方法,用于统计某字母在已输入列表中的出现次数:
class WordDataModel: ObservableObject { @Published var shuffleDisplay: Array<Character> = ["S", "T", "R", "E", "E", "T"] @Published var typedLetters: [Character] = [] } extension WordDataModel { // 统计已输入列表中指定字母的数量 func typedCount(for letter: Character) -> Int { typedLetters.filter { $0 == letter }.count } }
2. 修改ShuffleView的判断逻辑
在视图中,对每个位置的字母,先计算它在shuffleDisplay中是第几次出现,再和已输入的该字母数量对比,决定颜色:
import SwiftUI struct ShuffleView: View { @EnvironmentObject var dm: WordDataModel var body: some View { HStack(spacing: 3) { // 遍历shuffleDisplay的索引,避免使用未定义的boardLength ForEach(0..<dm.shuffleDisplay.count, id: \.self) { index in let letter = dm.shuffleDisplay[index] // 计算当前字母在shuffleDisplay中是第几次出现(从当前位置往前数) let currentOccurrence = dm.shuffleDisplay[0...index] .filter { $0 == letter } .count // 获取已输入的该字母数量 let typedCount = dm.typedCount(for: letter) Text(String(letter)) .font(.system(size: 50)) // 仅当当前出现次数 <= 已输入次数时,显示绿色 .foregroundColor(currentOccurrence <= typedCount ? .green : .blue) } } } }
逻辑说明
以单词"Street"为例:
- 第一个"E"在索引3,
currentOccurrence为1;第二个"E"在索引4,currentOccurrence为2 - 当
typedLetters中有1个"E"时,第一个"E"满足1<=1变色,第二个"E"因2>1保持原色 - 当输入第二个"E"后,
typedCount变为2,两个"E"都满足条件变色 - 删除输入时,
typedLetters移除最后一个元素,typedCount减少,对应位置的字母恢复原色
内容的提问来源于stack exchange,提问作者Henry McCreight
相关产品推荐
相关产品推荐

