我有一个使用UIKeyboardWillShow&在几个不同的控制器中隐藏通知。我决定尝试整合将键盘视图移动到基于协议的扩展所需的逻辑。
这是我的协议
public protocol KeyboardType : class {
func keyboardWillShow(_ sender: Notification)
func keyboardWillHide(_ sender: Notification)
}
接下来,我为我的新协议添加了一个扩展,以便我需要做的就是实现我的“KeyboardType协议,我将获得访问必要的功能,以便用键盘移动我的视图:
这是我的扩展程序
public extension KeyboardType where Self: UIViewController {
func addObservers() {
NotificationCenter.default.addObserver(self, selector: #selector(Self.keyboardWillShow(_:)), name:NSNotification.Name.UIKeyboardWillShow, object: self.view.window)
NotificationCenter.default.addObserver(self, selector: #selector(Self.keyboardWillHide(_:)), name:NSNotification.Name.UIKeyboardWillHide, object: self.view.window)
}
func removeObservers() {
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: self.view.window)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: self.view.window)
}
func keyboardWillHide(_ sender: Notification) {
let userInfo: [AnyHashable : Any] = (sender as NSNotification).userInfo!
let keyboardSize: CGSize = (userInfo[UIKeyboardFrameBeginUserInfoKey]! as AnyObject).cgRectValue.size
self.view.frame.origin.y += keyboardSize.height
}
func keyboardWillShow(_ sender: Notification) {
let userInfo: [AnyHashable : Any] = sender.userInfo!
let keyboardSize: CGSize = (userInfo[UIKeyboardFrameBeginUserInfoKey]! as AnyObject).cgRectValue.size
let offset: CGSize = (userInfo[UIKeyboardFrameEndUserInfoKey]! as AnyObject).cgRectValue.size
if keyboardSize.height == offset.height {
if self.view.frame.origin.y == 0 {
UIView.animate(withDuration: 0.1, animations: { () -> Void in
self.view.frame.origin.y -= keyboardSize.height
})
}
} else {
UIView.animate(withDuration: 0.1, animations: { () -> Void in
self.view.frame.origin.y += keyboardSize.height - offset.height
})
}
}
}
问题
问题是编译器要求我将@objc添加到我的keyboardWillShow和keyboardWillHide方法中。当我允许Xcode添加关键字时,编译器立即要求我删除@objc关键字。
'#selector'的参数是指实例方法'keyboardWillShow' 没有暴露于Objective-C
在这种情况下,如何将keyboardWillShow暴露给Objective-C?
或
有没有更好的方法来完成同样的任务?
答案 0 :(得分:1)
你试过这个吗?:
@objc public protocol KeyboardType {
func keyboardWillShow(_ sender: Notification)
func keyboardWillHide(_ sender: Notification)
}
您还需要导入UIKit
答案 1 :(得分:1)
我会采用不同的方法扩展UIViewController,如下所示:
protocol KeyboardController {
func keyboardWillShow(_ sender: Notification)
func keyboardWillHide(_ sender: Notification)
}
extension UIViewController: KeyboardController {
func addObservers() {
NotificationCenter.default.addObserver(self,
selector: #selector(keyboardWillShow(_:)),
name:.UIKeyboardWillShow,
object: view.window)
NotificationCenter.default.addObserver(self,
selector: #selector(keyboardWillHide(_:)),
name:.UIKeyboardWillHide,
object: view.window)
}
func removeObservers() {
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillShow, object: view.window)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillHide, object: view.window)
}
func keyboardWillHide(_ notification: Notification) {
print("---> keyboardWillHide")
guard let userInfo = notification.userInfo else { return }
let keyboardSize = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
print("keyboardSize", keyboardSize)
}
func keyboardWillShow(_ notification: Notification) {
print("---> keyboardWillShow")
guard
let userInfo = notification.userInfo,
let keyboardSize = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size,
let offset = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.size
else { return }
if keyboardSize.height == offset.height {
if self.view.frame.origin.y == 0 {
UIView.animate(withDuration: 0.1, animations: { () -> Void in
self.view.frame.origin.y -= keyboardSize.height
})
}
} else {
UIView.animate(withDuration: 0.1, animations: { () -> Void in
self.view.frame.origin.y += keyboardSize.height - offset.height
})
}
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
addObservers()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
另一个选项和我最喜欢的选项是子类UIViewController:
class KeyboardViewController: UIViewController {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
addObservers()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
removeObservers()
}
func addObservers() {
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_:)), name: .UIKeyboardWillShow, object: view.window)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(_:)), name: .UIKeyboardWillHide, object: view.window)
}
func removeObservers() {
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillShow, object: view.window)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillHide, object: view.window)
}
func keyboardWillHide(_ notification: Notification) {
print("---> keyboardWillHide")
if let keyboardHeight = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size.height {
print("keyboardHeight", keyboardHeight)
view.frame.origin.y += keyboardHeight
}
}
func keyboardWillShow(_ notification: Notification) {
print("---> keyboardWillShow")
if let userInfo = notification.userInfo,
let keyboardHeight = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size.height,
let offsetHeight = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.size.height {
print("userInfo", userInfo)
print("keyboardHeight", keyboardHeight)
print("offsetHeight", offsetHeight)
if keyboardHeight == offsetHeight {
if self.view.frame.origin.y == 0 {
UIView.animate(withDuration: 0.1, animations: { () -> Void in
self.view.frame.origin.y -= keyboardHeight
})
}
} else {
UIView.animate(withDuration: 0.1, animations: { () -> Void in
self.view.frame.origin.y += keyboardHeight - offsetHeight
})
}
}
}
}
class ViewController: KeyboardViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}