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

Posted

技术标签:

【中文标题】用于扩展非泛型类型的尾随 where 子句【英文标题】:Trailing where clause for extension of non-generic type 【发布时间】:2016-03-23 08:52:30 【问题描述】:

我有以下代码:

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

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

【问题讨论】:

【参考方案1】:

解决方法很简单,在扩展子句中切换顺序:

extension UIViewController where Self: KeyboardNotificationDelegate

应该是

extension KeyboardNotificationDelegate where Self: UIViewController

【讨论】:

这对我帮助很大。我正在做相反的事情,extension UIViewController where Self: UICollectionViewDelegate,但我没有意识到它需要与左侧的代表一起翻转。 感谢您提出这个问题!这有帮助!【参考方案2】:

extension Foo where ... 只能在Foo 为时使用

    泛型类或结构:使用符合某些类型约束的泛型的默认实现进行扩展, 包含一些关联类型的协议,在关联类型符合某些类型约束时扩展了默认实现 当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 的情况使用默认实现扩展您的委托协议,而不是尝试扩展 UIViewController

【讨论】:

以上是关于用于扩展非泛型类型的尾随 where 子句的主要内容,如果未能解决你的问题,请参考以下文章

C#泛型类容器

C# where用法解析

C# 2.0 新特性(上)

泛型和枚举

是否可以使用 .NET 泛型类实现 COM 接口?

Java泛型