尾随where子句用于扩展非泛型类型

Sun*_*kas 32 ios swift swift2 protocol-extension swift2.2

我有以下代码:

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:"))
    }
}
Run Code Online (Sandbox Code Playgroud)

在延伸UIViewController.许多viewcontroller重用此代码来注册键盘通知.但是使用Swift 2.2会产生警告.我喜欢新的#selector语法,但不知道在这种情况下如何实现它.

我认为正确的解决方案是制定协议并UIViewController仅针对符合该协议的实例进行扩展.我的代码到目前为止:

@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(_:)))
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然而,这让我错了

trailing where clause for extension of non-generic type
Run Code Online (Sandbox Code Playgroud)

在扩展行上.有任何想法吗?

Sun*_*kas 64

解决方案很容易在扩展子句中切换顺序:

extension UIViewController where Self: KeyboardNotificationDelegate
Run Code Online (Sandbox Code Playgroud)

应该

extension KeyboardNotificationDelegate where Self: UIViewController
Run Code Online (Sandbox Code Playgroud)

  • 这对我很有帮助.我正在做相反的方式,`扩展UIViewController其中Self:UICollectionViewDelegate`但我没有意识到它需要与左边的委托一起翻转. (3认同)

dfr*_*fri 19

extension Foo where ...如果只能用Foo

  1. 泛型类或结构:使用符合某种类型约束的泛型的默认实现进行扩展,
  2. 包含一些关联类型的协议,当关联类型符合某种类型约束时,使用默认实现进行扩展
  3. 我们使用默认实现扩展的协议,用于何时Self属于特定(对象/引用)类型,或符合某种类型约束.

例如

// 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
Run Code Online (Sandbox Code Playgroud)

在您的情况下,UIViewController是非泛型类类型,它不符合上述任何一种类型.


正如您在自己的答案中所写的那样,解决方案是使用默认实现来扩展您的委托协议Self: UIViewController,而不是尝试扩展UIViewController.