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

时间:2016-03-23 08:52:31

标签: 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:"))
    }
}

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(_:)))
        }
    }
}

然而这让我错误

trailing where clause for extension of non-generic type

在扩展行上。有什么想法吗?

2 个答案:

答案 0 :(得分:61)

解决方案很简单,可以在扩展条款中切换顺序:

extension UIViewController where Self: KeyboardNotificationDelegate

应该是

extension KeyboardNotificationDelegate where Self: UIViewController

答案 1 :(得分:19)

public void play(String mrlPathFile) { // URI encode for avoid non ascii character problem in windows!!! mrlPathFile = new File(mrlPathFile).toURI().toASCIIString().replace("file:/", "file:///"); mediaPlayer.playMedia(mrlPathFile); } 只能在extension Foo where ...

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

    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 是非泛型类类型,不符合上述任何一种类型。

    正如您在自己的答案中所写,解决方案是使用UIViewController的情况扩展您的委托协议,而不是尝试扩展Self: UIViewController