我正在尝试制作ViewControllers可以实现的协议,以调整其视图以适应键盘显示/隐藏。
protocol KeyboardAdaptable {
func keyboardWillShow(notification: NSNotification)
func keyboardWillHide(notification: NSNotification)
func addKeyboardNotificationObservers()
}
extension KeyboardAdaptable where Self: UIViewController, Self: NSObject {
func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
if self.view.frame.origin.y == 0{
self.view.frame.origin.y -= keyboardSize.height
}
}
}
func keyboardWillHide(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
if self.view.frame.origin.y != 0{
self.view.frame.origin.y += keyboardSize.height
}
}
}
func addKeyboardNotificationObservers() {
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
}
错误:" #selector的参数是指实例方法&keyboard;' keyboardWillShow'没有暴露于Objective-C。"
我知道选择器是Objective-C的一个特性,引用的函数必须兼容。我试图通过标记协议本身以及使用@objc注释的方法来解决这个问题,但是编译器坚持我也在@objc的协议扩展中标记默认实现。当我这样做时,它大声叫我删除@objc注释,因为" @objc只能用于类成员,@ objc协议和类的具体扩展" (即不在协议扩展中?)
有谁知道实现这一目标的方法?我乍一看似乎没有办法解决它,但我也知道UIViewController是NSObject的孩子,并且通常允许UIViewControllers上的实例方法成为选择器的目标。我想通过在我的协议扩展上放置约束,要求它是UIViewController的子类,我可以使用选择器来定位其中包含的默认实现。
思想?
答案 0 :(得分:3)
无法完成。
每个人都首先认为这是一个很酷的主意,(包括我自己),但它根本无法做到。
Swift协议扩展对于Objective-C是不可见的。对此无能为力。即使#selector
无法正常工作,因为:
您的协议功能仅在协议扩展中定义 。
人们一直试图通过协议扩展将Objective-C可调用功能(选择器,委托方法,等等)注入到类中。遗憾。
答案 1 :(得分:2)
我完全同意之前的回答 - 这无法完成。但是我决定愚弄你的代码并创建我能找到的最可接受的解决方案。也许它会派上用场:
class KeyboardAdapter {
private weak var view: UIView!
init(view: UIView) {
self.view = view
addKeyboardNotificationObservers()
}
@objc
func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
if self.view.frame.origin.y == 0 {
self.view.frame.origin.y -= keyboardSize.height
}
}
}
@objc
func keyboardWillHide(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
if self.view.frame.origin.y != 0 {
self.view.frame.origin.y += keyboardSize.height
}
}
}
private func addKeyboardNotificationObservers() {
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
}
protocol KeyboardAdaptable: class {
var keyboardAdapter: KeyboardAdapter! { get set }
func configureAdapter()
}
extension KeyboardAdaptable where Self: UIViewController {
func configureAdapter() {
keyboardAdapter = KeyboardAdapter(view: self.view)
}
}