如何在 Swift 3 中编写键盘通知
How to write Keyboard notifications in Swift 3
我正在尝试将此代码更新为 swift 3:
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name: UIKeyboardWillHideNotification, object: nil)`
到目前为止,我只是尝试了编译器提供的自动更正。这导致代码如下:
let notificationCenter = NotificationCenter.default()
notificationCenter.addObserver(self, selector: Selector(("keyboardWillShow:")), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
notificationCenter.addObserver(self, selector: Selector(("keyboardWillHide:")), name: NSNotification.Name.UIKeyboardWillHide, object: nil)`
不幸的是,这并没有带我走多远,导致了额外的错误。
请问有人解决了吗?
请注意,我只是在尝试如何编写通知。我(还)没有尝试修复通知功能。谢谢
您可以将已弃用的字符串文字 Selector
替换为经过类型检查的 #selector(Class.method)
对:
let center = NotificationCenter.default
center.addObserver(self,
selector: #selector(keyboardWillShow(_:)),
name: .UIKeyboardWillShow,
object: nil)
center.addObserver(self,
selector: #selector(keyboardWillHide(_:)),
name: .UIKeyboardWillHide,
object: nil)
#selector
语法更安全,因为 Swift 能够在编译时检查指定的方法是否实际存在。
有关 Swift 选择器的详细信息,请参阅 rickster's detailed answer。
我通过编写这样的代码解决了这个问题
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: .UIKeyboardWillShow, object: nil)
您可以分别在两个版本的 Swift 上执行键盘通知。
添加对象服务器:
NotificationCenter.default.addObserver(self, selector: #selector(keyboardDidShow), name: .UIKeyboardWillShow, object: nil)
调用函数swift3
func keyboardDidShow() {
print("keyboardDidShow")
}
在swift4
中调用函数
@objc func keyboardDidShow() {
print("keyboardDidShow")
}
在Swift3.0
override func viewDidLoad()
{
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
键盘显示和隐藏
func keyboardWillShow(notification: NSNotification)
{
// Your Code Here
}
func keyboardWillHide(notification: NSNotification)
{
//Your Code Here
}
Swift 4
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
func keyboardWillShow(notification: NSNotification) {
print("keyboardWillShow")
}
func keyboardWillHide(notification: NSNotification){
print("keyboardWillHide")
}
deinit {
NotificationCenter.default.removeObserver(self)
}
您还可以在这些方法中使用以下代码获取键盘信息。
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChange), name: .UIKeyboardWillChangeFrame, object: nil) .
@objc func keyboardWillChange(notification: NSNotification) {
let duration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double
let curve = notification.userInfo![UIKeyboardAnimationCurveUserInfoKey] as! UInt
let curFrame = (notification.userInfo![UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
let targetFrame = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
let deltaY = targetFrame.origin.y - curFrame.origin.y
}
Swift 4.2 Xcode 10 (10L213o)
与Swift3相比主要变化在UIWindow.keyboardWillShowNotification
和UIWindow.keyboardWillHideNotification
let notifier = NotificationCenter.default
notifier.addObserver(self,
selector: #selector(KeyboardLayoutConstraint.keyboardWillShowNotification(_:)),
name: UIWindow.keyboardWillShowNotification,
object: nil)
notifier.addObserver(self,
selector: #selector(KeyboardLayoutConstraint.keyboardWillHideNotification(_:)),
name: UIWindow.keyboardWillHideNotification,
object: nil)
@objc
func keyboardWillShowNotification(_ notification: NSNotification) {}
@objc
func keyboardWillHideNotification(_ notification: NSNotification) {}
对于Swift 4.2
.UIKeyboardWillShow
重命名为 UIResponder.keyboardWillShowNotification
和
.UIKeyboardWillHide
重命名为 UIResponder.keyboardWillHideNotification
NotificationCenter.default.addObserver(self, selector: #selector(NameOfSelector), name: UIResponder.keyboardWillShowNotification , object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(NameOfSelector), name: UIResponder.keyboardWillHideNotification , object: nil)
@objc func NameOfSelector() {
//Actions when notification is received
}
NotificationCenter.default.addObserver(self, selector: Selector(("keyboardWillShow:")), name:UIResponder.keyboardWillShowNotification, object: nil);
NotificationCenter.default.addObserver(self, selector: Selector(("keyboardWillHide:")), name:UIResponder.keyboardWillHideNotification, object: nil);
Swift 5.1 + 组合 + SwiftUI
@State var keyboardHeight: CGFloat = 0 // or @Published if one is in ViewModel: ObservableObject
private var cancellableSet: Set<AnyCancellable> = []
init() {
let notificationCenter = NotificationCenter.default
notificationCenter.publisher(for: UIWindow.keyboardWillShowNotification)
.map {
guard
let info = [=10=].userInfo,
let keyboardFrame = info[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect
else { return 0 }
return keyboardFrame.height
}
.assign(to: \.keyboardHeight, on: self)
.store(in: &cancellableSet)
notificationCenter.publisher(for: UIWindow.keyboardDidHideNotification)
.map { _ in 0 }
.assign(to: \.keyboardHeight, on: self)
.store(in: &cancellableSet)
}
这是迄今为止最适合我的解决方案(来自 "Lets Build That App" YouTube 频道)
class ChatVC: UIViewController, UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate {
// reference to your UIView with message TextField
@IBOutlet weak var ChatView: UIView!
// bottom constrain to your UIView (in my case ChatView)
var bottomConstraint: NSLayoutConstraint?
override func viewDidLoad() {
super.viewDidLoad()
// add some text in the placeholder if you want
messageField.placeholder = "Type your message.."
// here we add two notifications for showing and hiding the keyboard
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotification), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotification), name: UIResponder.keyboardWillHideNotification, object: nil)
// defines the start position for message textField that will be shown on the screen
bottomConstraint = NSLayoutConstraint(item: ChatViewField!, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1, constant: -40)
view.addConstraint(bottomConstraint!)
}
// handles notifications for both cases when keyboard pops up and disappears
@objc func handleKeyboardNotification(notification: NSNotification){
if let userInfo = notification.userInfo {
let keyboardFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
print(keyboardFrame)
let isKeyboardShowing = notification.name == UIResponder.keyboardWillShowNotification
bottomConstraint?.constant = isKeyboardShowing ? -keyboardFrame.height : -40
// makes animation at the same time as the keyboard
UIView.animate(withDuration: 0, delay: 0, options: UIView.AnimationOptions.curveEaseOut, animations: {
self.view.layoutIfNeeded()
}) { (completed) in
}
}
}
您可以创建一个具有此逻辑的协议,并且您的 UIViewController 实现它,在 viewDidLoad
中调用配置方法来绑定它。
我在底部使用约束来移动整个视图,动画与键盘相同。
这里有一个使用 的例子:
protocol ViewControllerKeyboardType {
var bottomConstraint: NSLayoutConstraint! { get set }
func configKeyboardNotification()
func keyboardWillChangeHandler(notification: NSNotification)
}
extension ViewControllerKeyboardType where Self: UIViewController {
func keyboardWillChangeHandler(notification: NSNotification) {
let duration = notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double ?? 0.0
let curve = notification.userInfo?[UIResponder.keyboardAnimationCurveUserInfoKey] as? UInt ?? UIView.AnimationOptions.curveLinear.rawValue
let curFrame = (notification.userInfo![UIResponder.keyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
let targetFrame = (notification.userInfo![UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
let deltaY = targetFrame.origin.y - curFrame.origin.y
UIView.animate(withDuration: duration, delay: 0, options: UIView.AnimationOptions(rawValue: curve)) {
self.bottomConstraint.constant = self.bottomConstraint.constant - deltaY
self.view.layoutIfNeeded()
}
}
func configKeyboardNotification() {
NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillChangeFrameNotification, object: nil, queue: nil) { [weak self] (notification) in
self?.keyboardWillChangeHandler(notification: notification as NSNotification)
}
}
}
用法:
class MyViewController: UIViewController, ViewControllerKeyboardType {
@IBOutlet weak var bottomConstraint: NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
self.configKeyboardNotification()
}
}
我正在尝试将此代码更新为 swift 3:
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name: UIKeyboardWillHideNotification, object: nil)`
到目前为止,我只是尝试了编译器提供的自动更正。这导致代码如下:
let notificationCenter = NotificationCenter.default()
notificationCenter.addObserver(self, selector: Selector(("keyboardWillShow:")), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
notificationCenter.addObserver(self, selector: Selector(("keyboardWillHide:")), name: NSNotification.Name.UIKeyboardWillHide, object: nil)`
不幸的是,这并没有带我走多远,导致了额外的错误。
请问有人解决了吗?
请注意,我只是在尝试如何编写通知。我(还)没有尝试修复通知功能。谢谢
您可以将已弃用的字符串文字 Selector
替换为经过类型检查的 #selector(Class.method)
对:
let center = NotificationCenter.default
center.addObserver(self,
selector: #selector(keyboardWillShow(_:)),
name: .UIKeyboardWillShow,
object: nil)
center.addObserver(self,
selector: #selector(keyboardWillHide(_:)),
name: .UIKeyboardWillHide,
object: nil)
#selector
语法更安全,因为 Swift 能够在编译时检查指定的方法是否实际存在。
有关 Swift 选择器的详细信息,请参阅 rickster's detailed answer。
我通过编写这样的代码解决了这个问题
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: .UIKeyboardWillShow, object: nil)
您可以分别在两个版本的 Swift 上执行键盘通知。
添加对象服务器:
NotificationCenter.default.addObserver(self, selector: #selector(keyboardDidShow), name: .UIKeyboardWillShow, object: nil)
调用函数swift3
func keyboardDidShow() {
print("keyboardDidShow")
}
在swift4
中调用函数@objc func keyboardDidShow() {
print("keyboardDidShow")
}
在Swift3.0
override func viewDidLoad()
{
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
键盘显示和隐藏
func keyboardWillShow(notification: NSNotification)
{
// Your Code Here
}
func keyboardWillHide(notification: NSNotification)
{
//Your Code Here
}
Swift 4
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
func keyboardWillShow(notification: NSNotification) {
print("keyboardWillShow")
}
func keyboardWillHide(notification: NSNotification){
print("keyboardWillHide")
}
deinit {
NotificationCenter.default.removeObserver(self)
}
您还可以在这些方法中使用以下代码获取键盘信息。
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChange), name: .UIKeyboardWillChangeFrame, object: nil) .
@objc func keyboardWillChange(notification: NSNotification) {
let duration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double
let curve = notification.userInfo![UIKeyboardAnimationCurveUserInfoKey] as! UInt
let curFrame = (notification.userInfo![UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
let targetFrame = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
let deltaY = targetFrame.origin.y - curFrame.origin.y
}
Swift 4.2 Xcode 10 (10L213o)
与Swift3相比主要变化在UIWindow.keyboardWillShowNotification
和UIWindow.keyboardWillHideNotification
let notifier = NotificationCenter.default
notifier.addObserver(self,
selector: #selector(KeyboardLayoutConstraint.keyboardWillShowNotification(_:)),
name: UIWindow.keyboardWillShowNotification,
object: nil)
notifier.addObserver(self,
selector: #selector(KeyboardLayoutConstraint.keyboardWillHideNotification(_:)),
name: UIWindow.keyboardWillHideNotification,
object: nil)
@objc
func keyboardWillShowNotification(_ notification: NSNotification) {}
@objc
func keyboardWillHideNotification(_ notification: NSNotification) {}
对于Swift 4.2
.UIKeyboardWillShow
重命名为 UIResponder.keyboardWillShowNotification
和
.UIKeyboardWillHide
重命名为 UIResponder.keyboardWillHideNotification
NotificationCenter.default.addObserver(self, selector: #selector(NameOfSelector), name: UIResponder.keyboardWillShowNotification , object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(NameOfSelector), name: UIResponder.keyboardWillHideNotification , object: nil)
@objc func NameOfSelector() {
//Actions when notification is received
}
NotificationCenter.default.addObserver(self, selector: Selector(("keyboardWillShow:")), name:UIResponder.keyboardWillShowNotification, object: nil);
NotificationCenter.default.addObserver(self, selector: Selector(("keyboardWillHide:")), name:UIResponder.keyboardWillHideNotification, object: nil);
Swift 5.1 + 组合 + SwiftUI
@State var keyboardHeight: CGFloat = 0 // or @Published if one is in ViewModel: ObservableObject
private var cancellableSet: Set<AnyCancellable> = []
init() {
let notificationCenter = NotificationCenter.default
notificationCenter.publisher(for: UIWindow.keyboardWillShowNotification)
.map {
guard
let info = [=10=].userInfo,
let keyboardFrame = info[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect
else { return 0 }
return keyboardFrame.height
}
.assign(to: \.keyboardHeight, on: self)
.store(in: &cancellableSet)
notificationCenter.publisher(for: UIWindow.keyboardDidHideNotification)
.map { _ in 0 }
.assign(to: \.keyboardHeight, on: self)
.store(in: &cancellableSet)
}
这是迄今为止最适合我的解决方案(来自 "Lets Build That App" YouTube 频道)
class ChatVC: UIViewController, UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate {
// reference to your UIView with message TextField
@IBOutlet weak var ChatView: UIView!
// bottom constrain to your UIView (in my case ChatView)
var bottomConstraint: NSLayoutConstraint?
override func viewDidLoad() {
super.viewDidLoad()
// add some text in the placeholder if you want
messageField.placeholder = "Type your message.."
// here we add two notifications for showing and hiding the keyboard
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotification), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotification), name: UIResponder.keyboardWillHideNotification, object: nil)
// defines the start position for message textField that will be shown on the screen
bottomConstraint = NSLayoutConstraint(item: ChatViewField!, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1, constant: -40)
view.addConstraint(bottomConstraint!)
}
// handles notifications for both cases when keyboard pops up and disappears
@objc func handleKeyboardNotification(notification: NSNotification){
if let userInfo = notification.userInfo {
let keyboardFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
print(keyboardFrame)
let isKeyboardShowing = notification.name == UIResponder.keyboardWillShowNotification
bottomConstraint?.constant = isKeyboardShowing ? -keyboardFrame.height : -40
// makes animation at the same time as the keyboard
UIView.animate(withDuration: 0, delay: 0, options: UIView.AnimationOptions.curveEaseOut, animations: {
self.view.layoutIfNeeded()
}) { (completed) in
}
}
}
您可以创建一个具有此逻辑的协议,并且您的 UIViewController 实现它,在 viewDidLoad
中调用配置方法来绑定它。
我在底部使用约束来移动整个视图,动画与键盘相同。
这里有一个使用
protocol ViewControllerKeyboardType {
var bottomConstraint: NSLayoutConstraint! { get set }
func configKeyboardNotification()
func keyboardWillChangeHandler(notification: NSNotification)
}
extension ViewControllerKeyboardType where Self: UIViewController {
func keyboardWillChangeHandler(notification: NSNotification) {
let duration = notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double ?? 0.0
let curve = notification.userInfo?[UIResponder.keyboardAnimationCurveUserInfoKey] as? UInt ?? UIView.AnimationOptions.curveLinear.rawValue
let curFrame = (notification.userInfo![UIResponder.keyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
let targetFrame = (notification.userInfo![UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
let deltaY = targetFrame.origin.y - curFrame.origin.y
UIView.animate(withDuration: duration, delay: 0, options: UIView.AnimationOptions(rawValue: curve)) {
self.bottomConstraint.constant = self.bottomConstraint.constant - deltaY
self.view.layoutIfNeeded()
}
}
func configKeyboardNotification() {
NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillChangeFrameNotification, object: nil, queue: nil) { [weak self] (notification) in
self?.keyboardWillChangeHandler(notification: notification as NSNotification)
}
}
}
用法:
class MyViewController: UIViewController, ViewControllerKeyboardType {
@IBOutlet weak var bottomConstraint: NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
self.configKeyboardNotification()
}
}