拼写页面增加大小写切换按钮,偏好持久化缓存

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-07-20 21:26:29 +08:00
parent 69a1c44ded
commit b693874f69
@@ -41,9 +41,18 @@ final class QuizViewController: UIViewController {
questions.indices.contains(currentIndex) ? questions[currentIndex] : nil questions.indices.contains(currentIndex) ? questions[currentIndex] : nil
} }
private var isUppercase: Bool
init(config: QuizConfig) { init(config: QuizConfig) {
self.config = config self.config = config
self.questions = QuizGenerator.makeQuestions(mode: config.mode, words: config.words) let uppercase = UserDefaults.standard.bool(forKey: "spelling_uppercase")
self.isUppercase = uppercase
let words = config.words.map { word in
let text = uppercase ? word.word.uppercased() : word.word.lowercased()
return Word(word: text, phonetic: word.phonetic, meaning: word.meaning,
example: word.example, exampleMeaning: word.exampleMeaning)
}
self.questions = QuizGenerator.makeQuestions(mode: config.mode, words: words)
super.init(nibName: nil, bundle: nil) super.init(nibName: nil, bundle: nil)
} }
@@ -59,6 +68,10 @@ final class QuizViewController: UIViewController {
view.backgroundColor = .systemBackground view.backgroundColor = .systemBackground
title = config.mode.rawValue title = config.mode.rawValue
navigationItem.largeTitleDisplayMode = .never navigationItem.largeTitleDisplayMode = .never
navigationItem.leftBarButtonItem = UIBarButtonItem(
image: UIImage(systemName: "textformat"),
style: .plain, target: self, action: #selector(toggleCase))
updateCaseButton()
buildLayout() buildLayout()
showQuestion() showQuestion()
} }
@@ -331,7 +344,7 @@ final class QuizViewController: UIViewController {
private func submitSpelling(_ typed: String, for question: QuizQuestion) { private func submitSpelling(_ typed: String, for question: QuizQuestion) {
guard selectedOption == nil else { return } guard selectedOption == nil else { return }
selectedOption = typed selectedOption = typed
let correct = typed == question.answer let correct = typed.lowercased() == question.answer.lowercased()
if !correct { if !correct {
wrongWords.append(question.word) wrongWords.append(question.word)
} }
@@ -344,7 +357,7 @@ final class QuizViewController: UIViewController {
private func submitDictation(_ typed: String, for question: QuizQuestion) { private func submitDictation(_ typed: String, for question: QuizQuestion) {
guard selectedOption == nil else { return } guard selectedOption == nil else { return }
selectedOption = typed selectedOption = typed
let correct = typed == question.answer let correct = typed.lowercased() == question.answer.lowercased()
if !correct { if !correct {
wrongWords.append(question.word) wrongWords.append(question.word)
} }
@@ -390,6 +403,17 @@ final class QuizViewController: UIViewController {
} }
} }
@objc private func toggleCase() {
isUppercase.toggle()
UserDefaults.standard.set(isUppercase, forKey: "spelling_uppercase")
updateCaseButton()
restart()
}
private func updateCaseButton() {
navigationItem.leftBarButtonItem?.tintColor = isUppercase ? Theme.Color.accent : .tertiaryLabel
}
@objc private func speakCurrentWord() { @objc private func speakCurrentWord() {
guard let question = current else { return } guard let question = current else { return }
speech.speak(question.word.word) speech.speak(question.word.word)
@@ -465,7 +489,12 @@ final class QuizViewController: UIViewController {
countdownTimer?.invalidate() countdownTimer?.invalidate()
countdownLabel.isHidden = true countdownLabel.isHidden = true
view.subviews.compactMap { $0 as? QuizResultView }.forEach { $0.removeFromSuperview() } view.subviews.compactMap { $0 as? QuizResultView }.forEach { $0.removeFromSuperview() }
questions = QuizGenerator.makeQuestions(mode: config.mode, words: config.words) let words = config.words.map { word in
let text = isUppercase ? word.word.uppercased() : word.word.lowercased()
return Word(word: text, phonetic: word.phonetic, meaning: word.meaning,
example: word.example, exampleMeaning: word.exampleMeaning)
}
questions = QuizGenerator.makeQuestions(mode: config.mode, words: words)
currentIndex = 0 currentIndex = 0
wrongWords = [] wrongWords = []
startDate = .now startDate = .now