有没有办法向 AnyObject 添加扩展?
Is there a way to add an extension to AnyObject?
在 Objective-C 中,我创建了 NSObject
的一个非常方便的类别(扩展,在 Swift 术语中),添加了添加任意 key/value 对的能力任何 NSObject
在运行时。它使用关联对象将可变字典附加到对象,然后提供 get/set key/value 对 to/from 该字典的 get 和 set 方法。只有几行代码。
这使得在运行时将任意 key/value 对附加到任何对象成为可能,包括系统创建的对象。这就是关键。在某些情况下,系统框架 returns 是您的一个对象,您需要能够为其附加一个值。
这个技巧还可以创建具有新实例变量的类别。 (好吧,他们不是真的,但它确实允许您向类别中的对象添加新的状态变量。)
这在 Swift 1.2 中是不可能的,因为:
- Swift 没有像 NSObject 这样的所有对象的基础 class
Objective-C。它使用 AnyObject,这是一种协议。
- Swift 1.2
不允许扩展协议。
在 Swift 1.2 下我不得不放弃这个。
但是Swift 2 允许对协议进行扩展。我以为"Great, now I can add my extension that lets me add key/value pairs to AnyObject!"
不开心。
当我尝试为 AnyObject 创建扩展时:
extension AnyObject: AssociatedObjectProtocol
我收到错误消息
'AnyObject' Protocol cannot be extended
哎呀!如此接近,但没有。似乎该语言明确禁止扩展 AnyObject。为什么会这样,有什么解决办法吗?
我不经常在 NSObject 上使用我的类别,但当我这样做时,它就是我的救星。我想将它添加到 Swift.
中的技巧包中
我可以像在 Objective-C 中那样将它添加到 NSObject,但这意味着它仅适用于从 NSObject 继承的对象 - 使其不适用于本机 Swift class是的。
不幸的是,不存在与您想要的完全相同的解决方法。所以我建议做一个协议,它有一个扩展来添加默认实现:
protocol A: AnyObject {}
// in Swift you would rather use this
protocol A: class {}
// add default implementations
extension A {
func aMethod() {
// code
}
}
// Example
class B: A {}
// use the method
B().aMethod()
这种方式不会让所有的类都自动遵守这个协议(但只有类可以遵守)。所以你必须让他们符合你自己。由于您不太使用它,因此这将是一个合理的解决方案。
按照@Qbyte 的回答,声明 NSObject
符合协议意味着整个 Cocoa/UIKit/Foundation 宇宙中几乎每个 class 都将继承该功能:
protocol MyProtocol {
func doSomething()
}
extension MyProtocol {
func doSomething() {
print("This is me, doing something.")
}
}
extension NSObject: MyProtocol { }
您刚刚使 Apple 框架 classes 的 99% 符合 MyProtocol
。您可以通过继承 NSObject
或简单地遵循它,使您自己的 class 符合 MyProtocol
。
我觉得你的答案就在你面前。扩展 NSObject
在 Swift 中也能完美工作。 (也许不是 6 年前)
extension NSObject { }
在 Objective-C 中,我创建了 NSObject
的一个非常方便的类别(扩展,在 Swift 术语中),添加了添加任意 key/value 对的能力任何 NSObject
在运行时。它使用关联对象将可变字典附加到对象,然后提供 get/set key/value 对 to/from 该字典的 get 和 set 方法。只有几行代码。
这使得在运行时将任意 key/value 对附加到任何对象成为可能,包括系统创建的对象。这就是关键。在某些情况下,系统框架 returns 是您的一个对象,您需要能够为其附加一个值。
这个技巧还可以创建具有新实例变量的类别。 (好吧,他们不是真的,但它确实允许您向类别中的对象添加新的状态变量。)
这在 Swift 1.2 中是不可能的,因为:
- Swift 没有像 NSObject 这样的所有对象的基础 class Objective-C。它使用 AnyObject,这是一种协议。
- Swift 1.2 不允许扩展协议。
在 Swift 1.2 下我不得不放弃这个。
但是Swift 2 允许对协议进行扩展。我以为"Great, now I can add my extension that lets me add key/value pairs to AnyObject!"
不开心。
当我尝试为 AnyObject 创建扩展时:
extension AnyObject: AssociatedObjectProtocol
我收到错误消息
'AnyObject' Protocol cannot be extended
哎呀!如此接近,但没有。似乎该语言明确禁止扩展 AnyObject。为什么会这样,有什么解决办法吗?
我不经常在 NSObject 上使用我的类别,但当我这样做时,它就是我的救星。我想将它添加到 Swift.
中的技巧包中我可以像在 Objective-C 中那样将它添加到 NSObject,但这意味着它仅适用于从 NSObject 继承的对象 - 使其不适用于本机 Swift class是的。
不幸的是,不存在与您想要的完全相同的解决方法。所以我建议做一个协议,它有一个扩展来添加默认实现:
protocol A: AnyObject {}
// in Swift you would rather use this
protocol A: class {}
// add default implementations
extension A {
func aMethod() {
// code
}
}
// Example
class B: A {}
// use the method
B().aMethod()
这种方式不会让所有的类都自动遵守这个协议(但只有类可以遵守)。所以你必须让他们符合你自己。由于您不太使用它,因此这将是一个合理的解决方案。
按照@Qbyte 的回答,声明 NSObject
符合协议意味着整个 Cocoa/UIKit/Foundation 宇宙中几乎每个 class 都将继承该功能:
protocol MyProtocol {
func doSomething()
}
extension MyProtocol {
func doSomething() {
print("This is me, doing something.")
}
}
extension NSObject: MyProtocol { }
您刚刚使 Apple 框架 classes 的 99% 符合 MyProtocol
。您可以通过继承 NSObject
或简单地遵循它,使您自己的 class 符合 MyProtocol
。
我觉得你的答案就在你面前。扩展 NSObject
在 Swift 中也能完美工作。 (也许不是 6 年前)
extension NSObject { }