You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 22:01:00