ios swift swift2 protocol-extension swift2.2

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á

  1. una clase o estructura genérica: ampliar con una implementación predeterminada para genéricos que se ajusten a alguna restricción de tipo,
  2. 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
  3. 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