ios - Trailing where cláusula para extensión de tipo no genérico
swift swift2 (2)
Tengo el siguiente código:
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:"))
}
}
en una extensión a UIViewController
. Este código es reutilizado por muchos viewcontroller para registrarse para notificaciones de teclado. Sin embargo, con Swift 2.2 produce una advertencia. Me gusta la nueva sintaxis de #selector
pero no estoy seguro de cómo implementarla en este caso.
Creo que la solución correcta es hacer un protocolo y extender UIViewController
solo para instancias que se ajusten a ese protocolo. Mi código hasta ahora:
@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(_:)))
}
}
}
Sin embargo, esto me da el error
trailing where clause for extension of non-generic type
en la fila de extensión. ¿Algunas ideas?
extension Foo where ...
solo se puede usar si Foo
está
- una clase o estructura genérica: ampliar con una implementación predeterminada para genéricos que se ajusten a alguna restricción de tipo,
- un protocolo que contiene algunos tipos asociados, se extiende con una implementación predeterminada para cuando un tipo asociado se ajusta a alguna restricción de tipo
- un protocolo en el que ampliamos con una implementación predeterminada para cuando
Self
es de un tipo específico (objeto / referencia), o cumple con alguna restricción de tipo.
P.ej
// 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
En su caso, UIViewController
es un tipo de clase no genérico, que no se ajusta a ninguno de los dos anteriores.
Como ha escrito en su propia respuesta, la solución es extender su protocolo delegado con una implementación predeterminada para los casos en que Self: UIViewController
, en lugar de intentar extender UIViewController
.
La solución fue simple para cambiar el orden en la cláusula de extensión:
extension UIViewController where Self: KeyboardNotificationDelegate
debiera ser
extension KeyboardNotificationDelegate where Self: UIViewController