web-dev-qa-db-ja.com

非ジェネリック型の拡張のための末尾のwhere句

私は次のコードを持っています:

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の拡張。このコードは、キーボード通知に登録するために多くのビューコントローラーによって再利用されます。ただし、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

拡張行。何か案は?

35
Sunkas

解決策は、拡張句の順序を切り替えるのが簡単でした。

extension UIViewController where Self: KeyboardNotificationDelegate

する必要があります

extension KeyboardNotificationDelegate where Self: UIViewController
67
Sunkas

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

あなたの場合、UIViewControllerは非ジェネリッククラス型であり、上記の2つのいずれにも適合しません。


あなた自身の答えで書いたように、解決策は、デリゲートプロトコルを、Self: UIViewControllerUIViewControllerを拡張しようとするのではなく。

19
dfri