用于扩展非泛型类型的尾随 where 子句
Trailing where clause for extension of non-generic type
我有以下代码:
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
在扩展行上。有什么想法吗?
解决方案很简单,只需切换扩展子句中的顺序即可:
extension UIViewController where Self: KeyboardNotificationDelegate
应该是
extension KeyboardNotificationDelegate where Self: UIViewController
extension Foo where ...
只能在 Foo
为
时使用
- 泛型 class 或结构:使用符合某些类型约束的泛型的默认实现进行扩展,
- 包含一些关联类型的协议,当关联类型符合某些类型约束时,使用默认实现进行扩展
- 一个协议,当
Self
是特定 (object/reference) 类型或符合某种类型约束时,我们使用默认实现进行扩展。
例如
// 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
是一个非泛型 class 类型,不符合以上两个中的任何一个。
正如您在自己的回答中所写,解决方案是在 Self: UIViewController
的情况下使用默认实现扩展您的委托协议,而不是尝试扩展 UIViewController
.
我有以下代码:
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
在扩展行上。有什么想法吗?
解决方案很简单,只需切换扩展子句中的顺序即可:
extension UIViewController where Self: KeyboardNotificationDelegate
应该是
extension KeyboardNotificationDelegate where Self: UIViewController
extension Foo where ...
只能在 Foo
为
- 泛型 class 或结构:使用符合某些类型约束的泛型的默认实现进行扩展,
- 包含一些关联类型的协议,当关联类型符合某些类型约束时,使用默认实现进行扩展
- 一个协议,当
Self
是特定 (object/reference) 类型或符合某种类型约束时,我们使用默认实现进行扩展。
例如
// 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
是一个非泛型 class 类型,不符合以上两个中的任何一个。
正如您在自己的回答中所写,解决方案是在 Self: UIViewController
的情况下使用默认实现扩展您的委托协议,而不是尝试扩展 UIViewController
.