J'ai le code suivant:
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:"))
}
}
dans une extension à UIViewController
. Ce code est réutilisé par de nombreux viewcontroller pour s'inscrire aux notifications du clavier. Cependant avec Swift 2.2 il produit un avertissement. J'aime le nouveau #selector
syntaxe mais ne savez pas comment l'implémenter dans ce cas.
Je pense que la bonne solution est de créer un protocole et d'étendre UIViewController
uniquement pour les instances conformes à ce protocole. Mon code jusqu'à présent:
@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(_:)))
}
}
}
Mais cela me fait l'erreur
trailing where clause for extension of non-generic type
sur la ligne d'extension. Des idées?
La solution était simple de changer l'ordre dans la clause d'extension:
extension UIViewController where Self: KeyboardNotificationDelegate
devrait être
extension KeyboardNotificationDelegate where Self: UIViewController
extension Foo where ...
ne peut être utilisé que si Foo
est
Self
est d'un type spécifique (objet/référence), ou conforme à une contrainte de type.Par exemple.
// 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
Dans votre cas, UIViewController
est un type de classe non générique, qui n'est conforme à aucun des deux ci-dessus.
Comme vous l'avez écrit dans votre propre réponse, la solution consiste à étendre votre protocole délégué avec une implémentation par défaut pour les cas où Self: UIViewController
, plutôt que d'essayer d'étendre UIViewController
.