【发布时间】:2019-12-28 00:05:49
【问题描述】:
我看到的每个帖子都希望在用户完成 UITextField 编辑后关闭键盘。我发现每次我想再次开始编辑以使键盘重新出现时都必须点击 UITextField 很烦人。我需要始终保持键盘处于打开状态,以便在键入开始后立即开始下一个用户输入。
目前,如果在 textFieldShouldReturn -> true UITextFieldDelegate 方法中调用 UITextField resignFirstResponder 方法,我的代码只能作用于用户键盘输入。
我尝试了以下方法:
func textFieldShouldEndEditing(_ textField: UITextField) -> Bool { 错误的 }
//
// TestViewController.swift
// Hyperpolyglot
//
// Created by Alan Dripps on 10/02/2019.
// Copyright © 2019 Alan Dripps. All rights reserved.
//
import UIKit
import AVFoundation
class TestViewController: UIViewController, UITextFieldDelegate {
@IBOutlet weak var stackView: UIStackView!
@IBOutlet weak var prompt: UILabel!
@IBOutlet weak var synthesizeButton: UIButton!
@IBOutlet weak var instructions: UILabel!
@IBOutlet weak var englishAnswer: UITextField!
var words = [String]()
var testWords = [String]()
var useHomework: Bool!
var practiceWrongNoCorrectAnswer: Int!
var homeworkWrongNoCorrectAnswer: Int!
var questionCounter = 0
var showingQuestion = true
var chosenLanguage = String()
var language = String()
let wordsString = "Words"
var englishWord = String()
var foreignWord = String()
var attempted = Int()
var homeworkAttempted = Int()
var homework = Int()
override func viewDidLoad() {
super.viewDidLoad()
print("viewDidLoad questionCounter is: \(questionCounter)")
print("useHomework in viewDidLoad in TestViewController is: \(useHomework!)")
loadChosenLanguage()
loadWords()
print("testWords just before shuffle: \(testWords)")
testWords.shuffle()
print("testWords just after shuffle: \(testWords)")
if useHomework == true {
navigationItem.title = "Learn Homework"
} else {
navigationItem.title = "Learn \(chosenLanguage.capitalized)"
}
navigationItem.rightBarButtonItem =
UIBarButtonItem(title: "Reveal Answer", style: .plain , target: self, action: #selector(answerTapped))
stackView.transform = CGAffineTransform(scaleX: 0.8, y: 0.8)
stackView.alpha = 0
synthesizeButton.isEnabled = false
synthesizeButton.alpha = 0.25
englishAnswer.delegate = self
englishAnswer.layer.cornerRadius = 0.05 * englishAnswer.bounds.size.width
let placeholderColor = UIColor.systemGray
englishAnswer.attributedPlaceholder = NSAttributedString(string: "Tap here to answer", attributes: [NSAttributedString.Key.foregroundColor : placeholderColor])
askQuestion()
instructions.isHidden = true
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
//loadWords()
//print("testWords just before shuffle: \(testWords)")
//testWords.shuffle()
//print("testWords just after shuffle: \(testWords)")
//print("questionCounter in viewWillAppear in TestViewController is: \(questionCounter)")
englishAnswer.delegate = self
englishAnswer.returnKeyType = .done
}
func textFieldShouldReturn(_ englishAnswer: UITextField) -> Bool {
//englishAnswer.resignFirstResponder()
self.englishAnswer(englishAnswer)
return true
}
@IBAction func synthesizeButton(_ sender: UIButton) {
let utterance = AVSpeechUtterance(string: testWords[questionCounter].components(separatedBy: "::")[0])
utterance.voice = AVSpeechSynthesisVoice(language: "en-US")
utterance.rate = 0.5
let synthesizer = AVSpeechSynthesizer()
synthesizer.speak(utterance)
}
@IBAction func englishAnswer(_ sender: UITextField) {
print("Entered englishAnswer")
let trimmed = sender.text?.trimmingCharacters(in: .whitespacesAndNewlines)
print("trimmed?capitalized in englishAnswer in TestViewController is: \(trimmed?.capitalized ?? "")")
if trimmed?.capitalized == testWords[questionCounter].components(separatedBy: "::")[0] {
resetWordCounters()
if questionCounter + 1 < testWords.count {
questionCounter += 1
} else {
questionCounter = 0
}
if case prompt.textColor = UIColor(red: 0, green: 0.7, blue: 0,
alpha: 1) {
print("prompt.textColor in englishAnswer in
TestViewController is: \(prompt.textColor!)")
}
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
self.prepareForNextQuestion()
}
} else {
appendPracticeWord()
prompt.textColor = UIColor(red: 0.7, green: 0, blue: 0, alpha: 1)
synthesizeButton.isEnabled = true
synthesizeButton.alpha = 1
instructions.isHidden = false
}
englishAnswer.text?.removeAll()
englishAnswer.placeholder = nil
englishAnswer.isEnabled = false
englishAnswer.layer.borderColor = UIColor.lightGray.cgColor as CGColor
}
func loadChosenLanguage() {
if let defaults = UserDefaults(suiteName: "group.co.uk.tirnaelectronics.hyperpolyglot.todayview") {
if let savedChosenLanguage = defaults.object(forKey: "languageChosen") as? String {
print("savedChosen Language in loadChosenLanguage in TestViewController is: \(savedChosenLanguage)")
chosenLanguage = savedChosenLanguage
}
}
}
func loadWords() {
print("in loadWords in TestViewController")
if let defaults = UserDefaults(suiteName: "group.co.uk.tirnaelectronics.hyperpolyglot.todayview") {
print("after defaults in loadWords in TestViewController")
if var savedWords = defaults.object(forKey: "words") as? [String] {
words.removeAll()
testWords.removeAll()
words = savedWords
print("savedWords in loadWords in TestViewcontroller are: \(savedWords)")
print("words in loadWords in TestViewController are: \(words)")
for savedWord in savedWords {
let split = savedWord.components(separatedBy: "::")
if useHomework == false {
if split[7] == chosenLanguage {
testWords.append(savedWord)
print("testWords.append from chosenLanguage in loadWords in TestViewController are: \(testWords)")
}
} else {
if split[6] == "1" {
testWords.append(savedWord)
print("testWords.append from homework in loadWords in TestViewController are: \(testWords)")
}
}
}
savedWords.removeAll()
}
}
}
override func viewDidLayoutSubviews() {
//configureButtons()
}
func configureButtons() {
synthesizeButton.layer.cornerRadius = 0.5 * synthesizeButton.bounds.size.width
synthesizeButton.layer.borderColor = UIColor.lightGray.cgColor as CGColor
synthesizeButton.layer.borderWidth = 4.0
synthesizeButton.clipsToBounds = true
}
func resetWordCounters() {
print("questionCounter in resetWordCounters in TestViewController is: \(questionCounter)")
let resetCountersWord = testWords[questionCounter].components(separatedBy: "::")[1]
print("resetCountersWord in resetWordCounters in TestViewController is: \(resetCountersWord)")
if useHomework == false {
attempted += 1
} else {
homeworkAttempted += 1
}
if useHomework == false {
practiceWrongNoCorrectAnswer = 0
} else {
homeworkWrongNoCorrectAnswer = 0
}
var indexForTestWord = 0
for testWord in testWords {
if testWord.components(separatedBy: "::")[1] == resetCountersWord {
print("testWord equals resetCountersWord: \(resetCountersWord)")
let split = testWord.components(separatedBy: "::")
let firstWord = split[0]
let secondWord = split[1]
testWords.remove(at: indexForTestWord)
print("testWords.remove in resetWordCounters in TestViewController are: \(testWords)")
testWords.insert("\(firstWord)"+"::"+"\(secondWord)"+"::"+"\(practiceWrongNoCorrectAnswer!)"+"::"+"\(homeworkWrongNoCorrectAnswer!)"+"::"+"\(attempted)"+"::"+"\(homeworkAttempted)"+"::"+"\(homework)"+"::"+"\(language)", at: indexForTestWord)
print("testWords.insert in resetWordCounters in TestViewController: \(testWords)")
break
}
indexForTestWord += 1
}
print("indexForTestWord in resetWordCounters in TestViewController is: \(indexForTestWord)")
removeInsertWord(resetCountersWordPracticeWord: resetCountersWord)
}
func appendPracticeWord() {
if useHomework == false {
attempted += 1
} else {
homeworkAttempted += 1
}
if useHomework == false {
practiceWrongNoCorrectAnswer += 1
} else {
homeworkWrongNoCorrectAnswer += 1
}
print("questionCounter in appendPracticeWord in TestViewController is: \(questionCounter)")
let practiceWord = testWords[questionCounter].components(separatedBy: "::")[1]
print("practiceWord in appendPracticeWord in TestViewController is: \(practiceWord)")
var indexForPracticeWord = 0
for testWord in testWords {
if testWord.components(separatedBy: "::")[1] == practiceWord {
print("testWord equals practiceWord: \(practiceWord)")
let split = testWord.components(separatedBy: "::")
let firstWord = split[0]
let secondWord = split[1]
testWords.remove(at: indexForPracticeWord)
print("testWords.remove in appendPracticeWord in TestViewController: \(testWords)")
testWords.insert("\(firstWord)"+"::"+"\(secondWord)"+"::"+"\(practiceWrongNoCorrectAnswer!)"+"::"+"\(homeworkWrongNoCorrectAnswer!)"+"::"+"\(attempted)"+"::"+"\(homeworkAttempted)"+"::"+"\(homework)"+"::"+"\(language)", at: indexForPracticeWord)
print("testWords.insert in appendPracticeWord in TestViewController: \(testWords)")
break
}
indexForPracticeWord += 1
}
print("indexForPracticeWord in appendPracticeWord in TestViewController is: \(indexForPracticeWord)")
removeInsertWord(resetCountersWordPracticeWord: practiceWord)
}
func removeInsertWord(resetCountersWordPracticeWord: String) {
var indexForWord = 0
for word in words {
if word.components(separatedBy: "::")[1] == resetCountersWordPracticeWord {
print("word equals resetCountersWordPracticeWord: \(word)")
let split = word.components(separatedBy: "::")
let firstWord = split[0]
let secondWord = split[1]
words.remove(at: indexForWord)
print("words.remove in removeInsertWord in TestViewController are: \(words)")
words.insert("\(firstWord)"+"::"+"\(secondWord)"+"::"+"\(practiceWrongNoCorrectAnswer!)"+"::"+"\(homeworkWrongNoCorrectAnswer!)"+"::"+"\(attempted)"+"::"+"\(homeworkAttempted)"+"::"+"\(homework)"+"::"+"\(language)", at: indexForWord)
print("words.insert in removeInsertWord in TestViewController after insert: \(words)")
break
}
indexForWord += 1
}
print("indexForWord in removeInsertWord in TestViewController is: \(indexForWord)")
saveWords()
}
@objc func answerTapped() {
showEnglishQuestion()
}
func showEnglishQuestion() {
showingQuestion = !showingQuestion
if showingQuestion {
// we should be showing the question – reset!
prepareForNextQuestion()
navigationItem.rightBarButtonItem =
UIBarButtonItem(title: "Reveal Answer", style: .plain , target: self, action: #selector(answerTapped))
//englishAnswer.isEnabled = true
} else {
// we should be showing the answer – show it now, and set the color to be green
print("questionCounter before prompt.text in showEnglishQuestion in TestViewController is: \(questionCounter)")
prompt.text = testWords[questionCounter].components(separatedBy: "::")[0]
prompt.textColor = UIColor(red: 0, green: 0.7, blue: 0, alpha: 1)
print("testWords.count in askQuestion in TestViewController is: \(testWords.count)")
if questionCounter + 1 < testWords.count {
let showNextLanguage = testWords[questionCounter + 1] .components(separatedBy: "::")[7]
navigationItem.rightBarButtonItem =
UIBarButtonItem(title: "Next \(showNextLanguage.capitalized) Word", style: .plain , target: self, action: #selector(answerTapped))
print("showNextLanguage in showEnglishQuestion in TestViewController is: \(showNextLanguage)")
// move the question counter one place
questionCounter += 1
print("questionCounter in showEnglishQuestion in TestViewController is: \(questionCounter)")
} else {
// wrap it back to 0 if we've gone beyond the size of the array
questionCounter = 0
print("questionCounter in questionCounter = 0 else statement in showEnglishQuestion in TestViewController is: \(questionCounter)")
print("words array in showEnglishQuestion in TestViewController when questionCounter = 0 is: \(testWords)")
let showNextLanguage = testWords[questionCounter] .components(separatedBy: "::")[7]
navigationItem.rightBarButtonItem =
UIBarButtonItem(title: "Next \(showNextLanguage.capitalized) Word", style: .plain , target: self, action: #selector(answerTapped))
print("showNextLanguage in if questionCounter == 0 in showEnglishQuestion in TestViewController is: \(showNextLanguage)")
// move the question counter one place
}
englishAnswer.isEnabled = false
}
synthesizeButton.isEnabled = false
synthesizeButton.alpha = 0.25
instructions.isHidden = true
}
func askQuestion() {
// pull out the foreign word at the current question position
print("questionCounter before prompt.text in askQuestion in TestViewController is: \(questionCounter)")
prompt.text = testWords[questionCounter].components(separatedBy: "::")[1]
print("testWords[questionCounter] in askQuestion in TestViewController is: \(testWords[questionCounter].components(separatedBy: "::")[0])")
let animation = UIViewPropertyAnimator(duration: 0.5, dampingRatio: 0.5) {
self.stackView.alpha = 1
self.stackView.transform = CGAffineTransform.identity
}
animation.startAnimation()
englishAnswer.isEnabled = true
englishAnswer.layer.borderColor = UIColor.black.cgColor as CGColor
englishWord = testWords[questionCounter].components(separatedBy: "::")[0]
foreignWord = testWords[questionCounter].components(separatedBy: "::")[1]
practiceWrongNoCorrectAnswer = Int(testWords[questionCounter].components(separatedBy: "::")[2])!
homeworkWrongNoCorrectAnswer = Int(testWords[questionCounter].components(separatedBy: "::")[3])!
attempted = Int(testWords[questionCounter].components(separatedBy: "::")[4])!
homeworkAttempted = Int(testWords[questionCounter].components(separatedBy: "::")[5])!
homework = Int(testWords[questionCounter].components(separatedBy: "::")[6])!
language = testWords[questionCounter].components(separatedBy: "::")[7]
}
func prepareForNextQuestion() {
let animation = UIViewPropertyAnimator(duration: 0.5, curve: .easeInOut) { [unowned self] in
self.stackView.transform = CGAffineTransform(scaleX: 0.8, y: 0.8)
self.stackView.alpha = 0
}
animation.addCompletion { [unowned self] position in
self.prompt.textColor = UIColor.black
self.askQuestion()
}
animation.startAnimation()
englishAnswer.placeholder = "Tap here to answer"
}
func saveWords() {
if let defaults = UserDefaults(suiteName: "group.co.uk.tirnaelectronics.hyperpolyglot.todayview") {
defaults.set(words, forKey: "words")
}
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
}
*/
}
textFieldShouldEndEditing 方法停止键盘关闭,但没有将用户的编辑传递给我的发件人:UITextField 方法对输入有用。
【问题讨论】:
-
你可以在
textFieldShouldReturn函数中捕获相同的信息 -
如果只是删除所有resignFirstResponder,键盘不会消失。但是需要在最后提出一种隐藏键盘的方法。
-
@Lu_ 你的意思是捕获用户输入并像我在方法中那样处理它:IBAction func englishAnswer(_ sender: UITextField)?我不明白怎么做,因为 textFieldShouldReturn 中没有 _sender: UITextField 参数。
-
@claude31 没错,但就像我之前说的,用户的输入没有任何反应,它不会出现在 IBAction func englishAnswer(_ sender: UITextField) 方法中!
-
什么都没发生?你确定调用了函数吗?添加 print("Entered englishAnswer") 作为要检查的第一条语句。 EnglishAnswer IBAction 连接到什么?它是否连接到已发送的事件?哪个?
标签: ios swift keyboard uitextfield