Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift iOS-点击TextField、TextView和Background但丢失事件时删除视图_Swift_Uiview_Uitextfield_Uitextview_Uitapgesturerecognizer - Fatal编程技术网

Swift iOS-点击TextField、TextView和Background但丢失事件时删除视图

Swift iOS-点击TextField、TextView和Background但丢失事件时删除视图,swift,uiview,uitextfield,uitextview,uitapgesturerecognizer,Swift,Uiview,Uitextfield,Uitextview,Uitapgesturerecognizer,首先让我说,我玩编程,但我目前是一个新手 我混合了编程视图和故事板对象: 情节提要对象: 钮扣 文本字段 文本视图 程序视图: 消息标签 viewForMessageLabel 当我按下按钮时,添加了viewForMessageLabel。在viewDidLoad中,我添加了一个点击手势,以在点击背景时删除viewForMessageLabel。我还向文本字段添加了相同的点击手势,以删除viewForMessageLabel(如果存在)。我再次将相同的点击手势添加到文本字段以将其删除 如果键盘存

首先让我说,我玩编程,但我目前是一个新手

我混合了编程视图和故事板对象:

情节提要对象:

  • 钮扣
  • 文本字段
  • 文本视图
  • 程序视图:

  • 消息标签
  • viewForMessageLabel
  • 当我按下按钮时,添加了
    viewForMessageLabel
    。在
    viewDidLoad
    中,我添加了一个点击手势,以在点击背景时删除
    viewForMessageLabel
    。我还向文本字段添加了相同的点击手势,以删除
    viewForMessageLabel
    (如果存在)。我再次将相同的点击手势添加到文本字段以将其删除

    如果键盘存在,我会在文本字段中添加另一个点击手势,将其关闭。我注意到事情很古怪,我与事件失去了联系

    如果我在触摸背景时按下按钮添加标签,它不会被取消。如果我按下文本字段,它将关闭它并显示键盘。如果我再次按下按钮,文本字段仍处于打开状态,则会出现标签,我再次按下文本字段,但什么也没有发生。当我按return键隐藏键盘(我实现了该方法)时,键盘消失,按下按钮,出现
    viewForMessageLabel
    ,现在当我按文本字段时
    viewForMessageLabel
    消失。基本上,textField也发生了同样的事情

    我想要的是

  • 如果出现了
    viewForMessageLabel
    ,并且我按下了背景、文本字段或文本视图,它应该会消失

  • 如果textField或textView的键盘存在,并且我按下背景,键盘也应该消失

  • 我的代码:

    class ViewController: UIViewController, UITextFieldDelegate, UITextViewDelegate {
    
        //MARK:- Outlets
        @IBOutlet weak var textField: UITextField!
        @IBOutlet weak var textView: UITextView!
        @IBOutlet weak var button: UIButton!
    
        let messagelabel: UILabel = {
            let label = UILabel()
            label.translatesAutoresizingMaskIntoConstraints = false
            label.text = "Pizza Pizza Pizza Pizza Pizza"
            label.font = UIFont(name: "Helvetica-Regular", size: 17)
            label.sizeToFit()
            label.numberOfLines = 0
            label.textAlignment = .center
            label.textColor = UIColor.white
            label.backgroundColor = UIColor.clear
            return label
        }()
    
        let viewForMessageLabel: UIView = {
            let view = UIView()
            view.translatesAutoresizingMaskIntoConstraints = false
            view.backgroundColor = UIColor.red
            return view
        }()
    
        //View Controller Lifecycle
        override func viewDidLoad() {
            super.viewDidLoad()
    
            textField.delegate = self
            textView.delegate = self
    
            // 0. hide viewForMessageLabel is background is tapped
            let tapGesture = UITapGestureRecognizer(target: self, action: #selector(removeViewForMessageLabel))
            view.addGestureRecognizer(tapGesture)
    
            // 1. hide viewForMessageLabel if textView is tapped
            textView.addGestureRecognizer(tapGesture)
    
            // 2. hide keyboard if background if tapped
            let hideKeyboard = UITapGestureRecognizer(target: self, action: #selector(hideKeyboardWhenBackGroundTapped))
            view.addGestureRecognizer(hideKeyboard)
    
            // 3. hide keyboard if textView is tapped
            textView.addGestureRecognizer(hideKeyboard)
    
            // 4. hide viewForMessageLabel for textField if background is tapped
            textField.addTarget(self, action: #selector(removeViewForMessageLabel), for: .editingDidBegin)
    
        }
    
        //MARK:- Button
        @IBAction func buttonPressed(_ sender: UIButton) {
            view.addSubview(viewForMessageLabel)
            setViewForMessageLabelAnchors()
            setMessageLabelAnchors()
        }
    
        //MARK:- Functions
        func setViewForMessageLabelAnchors(){
            viewForMessageLabel.topAnchor.constraint(equalTo: view.topAnchor, constant: 44).isActive = true
            viewForMessageLabel.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 0).isActive = true
            viewForMessageLabel.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 0).isActive = true
            viewForMessageLabel.addSubview(messagelabel)
        }
    
        func setMessageLabelAnchors(){
            messagelabel.topAnchor.constraint(equalTo: viewForMessageLabel.topAnchor, constant: 0).isActive = true
            messagelabel.widthAnchor.constraint(equalTo: viewForMessageLabel.widthAnchor).isActive = true
            viewForMessageLabel.bottomAnchor.constraint(equalTo: messagelabel.bottomAnchor, constant: 0).isActive = true
        }
    
        func removeViewForMessageLabel(){
            viewForMessageLabel.removeFromSuperview()
        }
    
        func hideKeyboardWhenBackGroundTapped(){
            textField.resignFirstResponder()
        }
    
        //MARK:- TextField Delegate
        func textFieldShouldReturn(_ textField: UITextField) -> Bool {
            view.endEditing(true)
            return true
        }
    
        func textViewDidBeginEditing(_ textView: UITextView) {
            removeViewForMessageLabel()
        }
    
        //MARK:- TextView Delegate
        func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
            if(text == "\n") {
                textView.resignFirstResponder()
                return false
            }
            return true
        }
    }
    
  • 如果textField或textView的键盘存在,并且我按下背景,键盘也应该消失
  • 您将其表示为取决于当前是否显示键盘,但您的代码没有反映这一点(而且不应该反映这一点)。您可以随时调用
    resignFirstResponder
    ,这样就不会有什么不好的事情发生。您还可以对已删除的视图调用
    removeFromSuperview
    (请参阅)

    因此,我认为您只需将一个动作附加到一个点击手势识别器:

    var tapGesture: UITapGestureRecognizer?
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        textField.delegate = self
        textView.delegate = self
    
        // 0. hide viewForMessageLabel is background is tapped
        tapGesture = UITapGestureRecognizer(target: self, action: #selector(removeLabelAndHideKeyboard))
        view.addGestureRecognizer(tapGesture)
    
        // 1. hide viewForMessageLabel if textView is tapped
        textView.addGestureRecognizer(tapGesture)
    }
    
    func removeLabelAndHideKeyboard() {
        viewForMessageLabel.removeFromSuperview()
        textField.resignFirstResponder()
    }
    
  • 如果textField或textView的键盘存在,并且我按下背景,键盘也应该消失
  • 您将其表示为取决于当前是否显示键盘,但您的代码没有反映这一点(而且不应该反映这一点)。您可以随时调用
    resignFirstResponder
    ,这样就不会有什么不好的事情发生。您还可以对已删除的视图调用
    removeFromSuperview
    (请参阅)

    因此,我认为您只需将一个动作附加到一个点击手势识别器:

    var tapGesture: UITapGestureRecognizer?
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        textField.delegate = self
        textView.delegate = self
    
        // 0. hide viewForMessageLabel is background is tapped
        tapGesture = UITapGestureRecognizer(target: self, action: #selector(removeLabelAndHideKeyboard))
        view.addGestureRecognizer(tapGesture)
    
        // 1. hide viewForMessageLabel if textView is tapped
        textView.addGestureRecognizer(tapGesture)
    }
    
    func removeLabelAndHideKeyboard() {
        viewForMessageLabel.removeFromSuperview()
        textField.resignFirstResponder()
    }
    

    这并不能完全回答问题,但我找到了一个解决办法。如果我使用@Toddg建议的方法:

    func removeLabelAndHideKeyboard() {
        viewForMessageLabel.removeFromSuperview()
        textField.resignFirstResponder()
    }
    
    它在函数中添加了重新调整文本字段的功能,这非常有帮助

    在viewDidLoad中,我还添加了:

    textField.addTarget(self, action: #selector(removeViewForMessageLabel), for: .touchDown)
    
    这里的关键是使用.touchtdown而不是.editingdidbeagin。这样我就可以在textField和textView之间来回切换,键盘将对这两个字段做出响应。我必须再添加一件事——在textView的键盘上添加一个工具栏,该工具栏上的“完成”按钮可以关闭textView:

        func addDoneButtonOnKeyboard(){
            let toolBar = UIToolbar()
            toolBar.sizeToFit()
            doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(dismissKeyboard))
            toolBar.setItems([doneButton!], animated: true)
            textView.inputAccessoryView = toolBar
        }
    
        @objc func dismissTextViewKeyboard(){
            view.endEditing(true)
        }
    
    这样,当文本视图出现时,我可以将其忽略

    在所有情况下,如果我按textField、background或textView,并且ViewFormMessageLabel出现,它将消失

    如果文本字段是第一响应者,并且它的键盘存在,并且我按下背景,它将消失

    我还不知道如何在触摸背景和其他东西时关闭textView,所以我在工具栏上实现了一个“完成”按钮。如果我按下它,并且textView的键盘存在,当它调用我添加的
    dismissTextViewKeyboard()
    函数时,它将被解除。两者都在底部,其他所有内容都在viewDidLoad中

    如果有人有更好的答案,我会投赞成票

    class ViewController: UIViewController, UITextFieldDelegate, UITextViewDelegate {
    
    
        //MARK:- Outlets
        @IBOutlet weak var textField: UITextField!
        @IBOutlet weak var textView: UITextView!
        @IBOutlet weak var button: UIButton!
    
        let messagelabel: UILabel = {
            let label = UILabel()
            label.translatesAutoresizingMaskIntoConstraints = false
            label.text = "Pizza Pizza Pizza Pizza Pizza"
            label.font = UIFont(name: "Helvetica-Regular", size: 17)
            label.sizeToFit()
            label.numberOfLines = 0
            label.textAlignment = .center
            label.textColor = UIColor.white
            label.backgroundColor = UIColor.clear
            return label
        }()
    
        let viewForMessageLabel: UIView = {
            let view = UIView()
            view.translatesAutoresizingMaskIntoConstraints = false
            view.backgroundColor = UIColor.red
            return view
        }()
    
        fileprivate var doneButton: UIBarButtonItem?
    
        //View Controller Lifecycle
        override func viewDidLoad() {
            super.viewDidLoad()
    
            textField.delegate = self
            textView.delegate = self
    
            let tapGesture = UITapGestureRecognizer(target: self, action: #selector(removeViewForMessageLabel))
            view.addGestureRecognizer(tapGesture)
    
            textField.addTarget(self, action: #selector(removeViewForMessageLabel), for: .touchDown)
    
            addDoneButtonOnKeyboard()
        }
    
        //MARK:- Button
        @IBAction func buttonPressed(_ sender: UIButton) {
            //removeMessage()
            view.addSubview(viewForMessageLabel)
            setBackgroundAnchors()
            setMessageAndLabelAnchors()
        }
    
        //MARK:- Functions
        func setBackgroundAnchors(){
            viewForMessageLabel.topAnchor.constraint(equalTo: view.topAnchor, constant: 44).isActive = true
            viewForMessageLabel.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 0).isActive = true
            viewForMessageLabel.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 0).isActive = true
            viewForMessageLabel.addSubview(messagelabel)
        }
    
        func setMessageAndLabelAnchors(){
    
            messagelabel.topAnchor.constraint(equalTo: viewForMessageLabel.topAnchor, constant: 0).isActive = true
            messagelabel.widthAnchor.constraint(equalTo: viewForMessageLabel.widthAnchor).isActive = true
            viewForMessageLabel.bottomAnchor.constraint(equalTo: messagelabel.bottomAnchor, constant: 0).isActive = true
        }
    
        func removeViewForMessageLabel(){
            viewForMessageLabel.removeFromSuperview()
            textField.resignFirstResponder()
        }
    
        //MARK:- TextField Delegate
        func textFieldShouldReturn(_ textField: UITextField) -> Bool {
            view.endEditing(true)
            return true
        }
    
        func textViewDidBeginEditing(_ textView: UITextView) {
            removeViewForMessageLabel()
        }
    
        //MARK:- TextView Delegate
        func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
            if(text == "\n") {
                textView.resignFirstResponder()
                return false
            }
            return true
        }
    
        //MARK:- Additional Functions
        //add a done button to the keyboard when the textView is first responder
        fileprivate func addDoneButtonOnKeyboard(){
            let toolBar = UIToolbar()
            toolBar.sizeToFit()
            doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(dismissTextViewKeyboard))
            toolBar.setItems([doneButton!], animated: true)
            textView.inputAccessoryView = toolBar
        }
    
        //dismiss the keyboard when the Done button is tapped
        @objc func dismissTextViewKeyboard(){
            view.endEditing(true)
        }
    }
    

    这并不能完全回答问题,但我找到了一个解决办法。如果我使用@Toddg建议的方法:

    func removeLabelAndHideKeyboard() {
        viewForMessageLabel.removeFromSuperview()
        textField.resignFirstResponder()
    }
    
    它在函数中添加了重新调整文本字段的功能,这非常有帮助

    在viewDidLoad中,我还添加了:

    textField.addTarget(self, action: #selector(removeViewForMessageLabel), for: .touchDown)
    
    这里的关键是使用.touchtdown而不是.editingdidbeagin。这样我就可以在textField和textView之间来回切换,键盘将对这两个字段做出响应。我必须再添加一件事——在textView的键盘上添加一个工具栏,该工具栏上的“完成”按钮可以关闭textView:

        func addDoneButtonOnKeyboard(){
            let toolBar = UIToolbar()
            toolBar.sizeToFit()
            doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(dismissKeyboard))
            toolBar.setItems([doneButton!], animated: true)
            textView.inputAccessoryView = toolBar
        }
    
        @objc func dismissTextViewKeyboard(){
            view.endEditing(true)
        }
    
    这样,当文本视图出现时,我可以将其忽略

    在所有情况下,如果我按textField、background或textView,并且ViewFormMessageLabel出现,它将消失

    如果文本字段是第一响应者,并且它的键盘存在,并且我按下背景,它将消失

    我还不知道如何在触摸背景和其他东西时关闭textView,所以我在工具栏上实现了一个“完成”按钮。如果我按下它,并且textView的键盘存在,当它调用我添加的
    dismissTextViewKeyboard()
    函数时,它将被解除。两者都在底部,其他所有内容都在viewDidLoad中

    如果有人有更好的答案,我会投赞成票

    class ViewController: UIViewController, UITextFieldDelegate, UITextViewDelegate {
    
    
        //MARK:- Outlets
        @IBOutlet weak var textField: UITextField!
        @IBOutlet weak var textView: UITextView!
        @IBOutlet weak var button: UIButton!
    
        let messagelabel: UILabel = {
            let label = UILabel()
            label.translatesAutoresizingMaskIntoConstraints = false
            label.text = "Pizza Pizza Pizza Pizza Pizza"
            label.font = UIFont(name: "Helvetica-Regular", size: 17)
            label.sizeToFit()
            label.numberOfLines = 0
            label.textAlignment = .center
            label.textColor = UIColor.white
            label.backgroundColor = UIColor.clear
            return label
        }()
    
        let viewForMessageLabel: UIView = {
            let view = UIView()
            view.translatesAutoresizingMaskIntoConstraints = false
            view.backgroundColor = UIColor.red
            return view
        }()
    
        fileprivate var doneButton: UIBarButtonItem?
    
        //View Controller Lifecycle
        override func viewDidLoad() {
            super.viewDidLoad()
    
            textField.delegate = self
            textView.delegate = self
    
            let tapGesture = UITapGestureRecognizer(target: self, action: #selector(removeViewForMessageLabel))
            view.addGestureRecognizer(tapGesture)
    
            textField.addTarget(self, action: #selector(removeViewForMessageLabel), for: .touchDown)
    
            addDoneButtonOnKeyboard()
        }
    
        //MARK:- Button
        @IBAction func buttonPressed(_ sender: UIButton) {
            //removeMessage()
            view.addSubview(viewForMessageLabel)
            setBackgroundAnchors()
            setMessageAndLabelAnchors()
        }
    
        //MARK:- Functions
        func setBackgroundAnchors(){
            viewForMessageLabel.topAnchor.constraint(equalTo: view.topAnchor, constant: 44).isActive = true
            viewForMessageLabel.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 0).isActive = true
            viewForMessageLabel.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 0).isActive = true
            viewForMessageLabel.addSubview(messagelabel)
        }
    
        func setMessageAndLabelAnchors(){
    
            messagelabel.topAnchor.constraint(equalTo: viewForMessageLabel.topAnchor, constant: 0).isActive = true
            messagelabel.widthAnchor.constraint(equalTo: viewForMessageLabel.widthAnchor).isActive = true
            viewForMessageLabel.bottomAnchor.constraint(equalTo: messagelabel.bottomAnchor, constant: 0).isActive = true
        }
    
        func removeViewForMessageLabel(){
            viewForMessageLabel.removeFromSuperview()
            textField.resignFirstResponder()
        }
    
        //MARK:- TextField Delegate
        func textFieldShouldReturn(_ textField: UITextField) -> Bool {
            view.endEditing(true)
            return true
        }
    
        func textViewDidBeginEditing(_ textView: UITextView) {
            removeViewForMessageLabel()
        }
    
        //MARK:- TextView Delegate
        func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
            if(text == "\n") {
                textView.resignFirstResponder()
                return false
            }
            return true
        }
    
        //MARK:- Additional Functions
        //add a done button to the keyboard when the textView is first responder
        fileprivate func addDoneButtonOnKeyboard(){
            let toolBar = UIToolbar()
            toolBar.sizeToFit()
            doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(dismissTextViewKeyboard))
            toolBar.setItems([doneButton!], animated: true)
            textView.inputAccessoryView = toolBar
        }
    
        //dismiss the keyboard when the Done button is tapped
        @objc func dismissTextViewKeyboard(){
            view.endEditing(true)
        }
    }
    

    你有很多重叠的轻拍手势识别器。我不确定水龙头是否默认通过。“看来你把这件事搞得太复杂了。”托德,谢谢。我刚刚读到一篇帖子,上面说我可以在同一个点击中添加另一个动作。我要试试看。你为什么说我把事情复杂化了?你有很多重叠的轻拍动作记录