不要在 UITextField 返回时关闭键盘
Posted
技术标签:
【中文标题】不要在 UITextField 返回时关闭键盘【英文标题】:Don't dismiss keyboard on UITextField return 【发布时间】: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 连接到什么?它是否连接到已发送的事件?哪个?
【参考方案1】:
请将文本字段的委托添加到情节提要中的视图控制器或在 viewDidLoad 中设置“englishAnswer.delegate = self”
不要尝试在 textFieldShouldReturn 中返回 false。它不会有任何改变。
【讨论】:
我在 viewDidLoad 中设置了 englishAnswer.delegate = self 并在 textFieldShouldReturn 中返回 true。这是否应该将用户输入传递给我的方法,该方法对用户输入进行某些操作,因为与其他海报建议一样,我没有从应该检查用户正确回答问题的方法中得到任何响应。【参考方案2】:现在我明白了你的意思。你所做的一切都是正确的。然后在textFieldShouldEndEditing或textFieldShouldReturn中手动调用方法“self.englishAnswer(_sender:textField)。然后就可以了。你还没有在任何地方调用该方法。
【讨论】:
程序对错误/正确答案计数变量的正确或错误答案做出正确响应,但不得执行englishAnswer中的prompt.textColor行,因为正确答案应该变成绿色但不是不。程序进入 prompt.textColor 所在的条件测试,但 print test 语句似乎没有打印任何内容来调试 prompt.textColor 的控制台。提交输入后键盘仍然会退出,并且每次用户想要调出键盘回答新问题时都必须点击 UITextField。来源列表包含您的建议。以上是关于不要在 UITextField 返回时关闭键盘的主要内容,如果未能解决你的问题,请参考以下文章