I have the following code:
func registerNotification(name:String, selector:Selector)
{
NSNotificationCenter.defaultCenter().addObserver(self, selector: selector, name: name, object: nil)
}
func registerKeyboardNotifications()
{
let isInPopover = navigationController?.popoverPresentationController != nil
let ignore = isInPopover && DEVICE_IS_IPAD
if !ignore {
registerNotification(UIKeyboardWillShowNotification, selector: Selector("keyboardWillShow:"))
registerNotification(UIKeyboardWillHideNotification, selector: Selector("keyboardWillHide:"))
}
}
in an extension to UIViewController
. This code is reused by many viewcontroller to register for keyboard notifications. However with Swift 2.2 it produces a warning. I like the new #selector
syntax but not sure how to implement it in this case.
I think the correct solution is to make a protocol and extend UIViewController
only for instances that conform to that protocol. My code so far:
@objc protocol KeyboardNotificationDelegate
{
func keyboardWillShow(notification: NSNotification)
func keyboardWillHide(notification: NSNotification)
}
extension UIViewController where Self: KeyboardNotificationDelegate
{
func registerKeyboardNotifications()
{
let isInPopover = navigationController?.popoverPresentationController != nil
let ignore = isInPopover && DEVICE_IS_IPAD
if !ignore {
registerNotification(UIKeyboardWillShowNotification, selector: #selector(KeyboardNotificationDelegate.keyboardWillShow(_:)))
registerNotification(UIKeyboardWillHideNotification, selector: #selector(KeyboardNotificationDelegate.keyboardWillHide(_:)))
}
}
}
However this get me the error
trailing where clause for extension of non-generic type
on the extension row. Any ideas?
The solution was simple to switch the order in the extension clause:
extension UIViewController where Self: KeyboardNotificationDelegate
should be
extension KeyboardNotificationDelegate where Self: UIViewController
extension Foo where ...
can only be used if Foo
is
Self
is of a specific (object/reference) type, or conforms to some type constraint.E.g.
// 1
class Foo<T> { }
extension Foo where T: IntegerType {}
struct Foz<T> {}
extension Foz where T: IntegerType {}
// 2
protocol Bar {
associatedtype T
}
extension Bar where T: IntegerType {}
// 3
protocol Baz {}
extension Baz where Self: IntegerType {}
class Bax<T>: Baz {}
extension Baz where Self: Bax<Int> {
func foo() { print("foo") }
}
let a = Bax<Int>()
a.foo() // foo
In your case, UIViewController
is a non-generic class type, which does not conform to any of the two above.
As you've written in your own answer, the solution is to extend your delegate protocol with a default implementation for cases where Self: UIViewController
, rather than attempting to extend UIViewController
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With