Swift4下适配键盘移动视图后发送消息屏幕变黑问题求解
解决Swift4通用消息VC发送消息后屏幕黑屏的问题
嘿,我来帮你搞定这个发送消息后屏幕变黑的麻烦!结合你提到的添加键盘适配代码后出现的问题,大概率是键盘通知处理或者视图布局逻辑出了问题,下面给你几个常见的排查和解决方向:
1. 检查键盘通知是否正确移除
很多人只记得在viewDidLoad里添加键盘观察者,却忘了在控制器销毁时移除,这会导致重复触发通知、内存泄漏,甚至引发界面布局异常。
解决办法:在控制器的deinit方法里移除观察者:
deinit { NotificationCenter.default.removeObserver(self) }
2. 修正键盘收起时的视图复位逻辑
发送消息后通常会收起键盘,如果你的keyboardWillHide方法里视图复位的逻辑错误(比如偏移量计算不对、动画未正确执行),会导致视图被移到屏幕外,露出window的黑色背景,也就是你看到的黑屏。
举个正确的复位示例(假设你用ScrollView承载消息列表):
@objc func keyboardWillHide(_ notification: Notification) { guard let keyboardFrame = notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? CGRect else { return } let animationDuration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? Double ?? 0.25 UIView.animate(withDuration: animationDuration) { // 将scrollView的偏移量还原到键盘弹出前的状态 self.messagesScrollView.contentOffset.y -= keyboardFrame.height } }
如果是直接移动整个控制器的view,要确保复位到初始位置:
UIView.animate(withDuration: animationDuration) { self.view.frame.origin.y = 0 }
3. 改用Auto Layout约束适配键盘(更可靠)
手动修改view的frame很容易和Auto Layout约束冲突,导致布局错乱引发黑屏。推荐给输入框的底部约束创建一个IBOutlet,通过修改约束值来适配键盘:
步骤:
- 给输入框的底部约束添加IBOutlet:
@IBOutlet weak var inputBottomConstraint: NSLayoutConstraint! - 调整键盘通知的处理逻辑:
@objc func keyboardWillShow(_ notification: Notification) { guard let keyboardFrame = notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? CGRect else { return } let animationDuration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? Double ?? 0.25 inputBottomConstraint.constant = keyboardFrame.height UIView.animate(withDuration: animationDuration) { self.view.layoutIfNeeded() } } @objc func keyboardWillHide(_ notification: Notification) { let animationDuration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? Double ?? 0.25 inputBottomConstraint.constant = 0 // 还原到初始底部间距 UIView.animate(withDuration: animationDuration) { self.view.layoutIfNeeded() } }
4. 避免发送消息逻辑与键盘动画冲突
发送消息后你可能会刷新消息列表,如果这个操作和键盘收起动画同时执行,可能导致ScrollView的contentOffset计算错误,引发界面偏移。
解决办法:等键盘完全收起后再刷新列表:
func sendButtonTapped() { // 1. 收起键盘 messageTextField.resignFirstResponder() // 2. 执行发送消息的逻辑 if let messageText = messageTextField.text, !messageText.isEmpty { // 发送消息代码... messageTextField.text = "" } // 3. 等键盘动画完成后再刷新列表并滚动到最新消息 DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { self.messagesTableView.reloadData() if self.messages.count > 0 { let lastIndexPath = IndexPath(row: self.messages.count - 1, section: 0) self.messagesTableView.scrollToRow(at: lastIndexPath, at: .bottom, animated: true) } } }
你可以先从检查通知移除和键盘收起的复位逻辑开始排查,这两个是最常见的原因。如果还是有问题,建议改用Auto Layout的方式适配键盘,会减少很多布局冲突的问题。
内容的提问来源于stack exchange,提问作者naga
相关产品推荐
相关产品推荐

