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

Swift4中解决UITextField被iOS键盘遮挡时的滚动问题

Swift4 搞定底部UITextField被键盘遮挡的问题

嘿,我刚好在Swift4里踩过这个坑,给你分享两个亲测有效的方案,帮你解决键盘挡住底部输入框的问题!先看你的界面情况:

全屏状态:
全屏状态下的界面

键盘遮挡后的状态:
键盘遮挡UITextField的界面

你之前提到的那篇文章报错,是因为没正确关联contentView的高度约束,我下面也会专门讲这个问题的解决办法。

方案一:普通视图(没有用UIScrollView)

如果你的界面没有滚动视图,直接调整输入框的底部约束就行:

  1. 首先在Storyboard里给底部UITextField加一个底部约束,然后把这个约束拖成ViewController里的IBOutlet,比如叫textFieldBottomConstraint。
  2. 注册键盘弹出/收起的通知,动态调整约束值:
class ViewController: UIViewController {
    @IBOutlet weak var textFieldBottomConstraint: NSLayoutConstraint!
    @IBOutlet weak var bottomTextField: UITextField!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // 注册键盘通知(Swift4用UIResponder的静态属性,比旧版更规范)
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
    }
    
    // 键盘弹出时调整约束
    @objc func keyboardWillShow(notification: NSNotification) {
        guard let keyboardFrame = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect else { return }
        let keyboardHeight = keyboardFrame.height
        // 把底部约束改成键盘高度加个小间距(比如16),避免输入框贴键盘太近
        textFieldBottomConstraint.constant = keyboardHeight + 16
        // 用动画更新布局,过渡更自然
        UIView.animate(withDuration: 0.3) {
            self.view.layoutIfNeeded()
        }
    }
    
    // 键盘收起时恢复原约束
    @objc func keyboardWillHide(notification: NSNotification) {
        textFieldBottomConstraint.constant = 16 // 这里改成你原来的底部间距
        UIView.animate(withDuration: 0.3) {
            self.view.layoutIfNeeded()
        }
    }
    
    // 记得销毁时移除通知,避免内存泄漏
    deinit {
        NotificationCenter.default.removeObserver(self)
    }
}

方案二:用UIScrollView的情况(解决你之前的报错)

你之前遇到的self.constraintContentHeight.constant不是ViewController成员错误,是因为你没有把contentView的高度约束关联到ViewController里。按下面步骤来:

  1. 正确设置ScrollView的AutoLayout:

    • 给ScrollView加约束:上下左右都和父视图边缘对齐。
    • 在ScrollView里添加一个contentView(UIView),给contentView加约束:上下左右都和ScrollView的contentLayoutGuide对齐,同时contentView的宽度等于父视图的宽度(避免横向滚动)。
    • 给contentView加一个高度约束,这个约束就是我们要关联的constraintContentHeight。
  2. 关联约束IBOutlet:在ViewController里声明@IBOutlet weak var constraintContentHeight: NSLayoutConstraint!,然后在Storyboard里把contentView的高度约束拖到这个变量上。

  3. 然后同样用通知调整约束或者滚动位置:

class ViewController: UIViewController {
    @IBOutlet weak var scrollView: UIScrollView!
    @IBOutlet weak var constraintContentHeight: NSLayoutConstraint!
    @IBOutlet weak var bottomTextField: UITextField!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
        // 如果要在编辑时自动滚动,记得设置输入框代理
        bottomTextField.delegate = self
    }
    
    @objc func keyboardWillShow(notification: NSNotification) {
        guard let keyboardFrame = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect else { return }
        let keyboardHeight = keyboardFrame.height
        
        // 方法一:调整contentView高度,让输入框能被滚动到
        constraintContentHeight.constant = self.view.frame.height + keyboardHeight
        
        // 方法二:直接滚动到输入框位置(更精准)
        let textFieldFrame = bottomTextField.frame
        scrollView.scrollRectToVisible(textFieldFrame, animated: true)
    }
    
    @objc func keyboardWillHide(notification: NSNotification) {
        // 恢复contentView高度
        constraintContentHeight.constant = self.view.frame.height
        // 滚动回顶部
        scrollView.setContentOffset(CGPoint.zero, animated: true)
    }
    
    deinit {
        NotificationCenter.default.removeObserver(self)
    }
}

// 加上输入框代理,编辑时自动滚动
extension ViewController: UITextFieldDelegate {
    func textFieldDidBeginEditing(_ textField: UITextField) {
        let point = textField.convert(CGPoint.zero, to: scrollView)
        // 滚动到输入框上方,留16间距
        scrollView.setContentOffset(CGPoint(x: 0, y: point.y - 16), animated: true)
    }
    
    func textFieldDidEndEditing(_ textField: UITextField) {
        scrollView.setContentOffset(CGPoint.zero, animated: true)
    }
}

这样就不会再出现之前的错误了,因为constraintContentHeight已经被正确关联到Storyboard的约束上啦!

内容的提问来源于stack exchange,提问作者Augusto

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:41:32