语法层面是不支持的,与OC一样通常使用关联对象实现
本文书写时Swift5.6
第一种
第一种就是static var修饰的变量加&,或者全局的 var 变量加&
通过这种方式添加的属性和被拓展的类 不需要通过@objc修饰,不需要非得继承NSObject
class Test {
}
// or
// var testKey: String?
// var test1Key: String?
extension Test {
private static var testKey = true
var test: String {
get {
return objc_getAssociatedObject(self, &Self.testKey) as! String
}
set {
objc_setAssociatedObject(self, &Self.testKey, newValue, .OBJC_ASSOCIATION_COPY)
}
}
private static var test1Key = true
var test1: String {
get {
return objc_getAssociatedObject(self, &Self.test1Key) as! String
}
set {
objc_setAssociatedObject(self, &Self.test1Key, newValue, .OBJC_ASSOCIATION_COPY)
}
}
}
do {
let obj = Test()
obj.test = "123"
obj.test1 = "789"
print(obj.test)
print(obj.test1)
}
do {
let obj = Test()
obj.test = "456"
obj.test1 = "000"
print(obj.test)
print(obj.test1)
}
do {
let obj = Test()
obj.test = "999"
obj.test1 = "555"
print(obj.test)
print(obj.test1)
}
第二种
通过selector当前属性的setter or getter 方法,相当于OC时的_cmd & @selector()
通过这种方式添加的属性 需要通过@objc修饰,因为#selector()只能包裹被@objc修饰的方法,不需要非得继承NSObject
extension NSObject {
func setAssociated(key: Selector, value: Any?, policy: objc_AssociationPolicy) {
let p = unsafeBitCast(key, to: UnsafeRawPointer.self)
objc_setAssociatedObject(self, p, value, policy)
}
func getAssociated<T>(key: Selector) -> T? {
let p = unsafeBitCast(key, to: UnsafeRawPointer.self)
return objc_getAssociatedObject(self, p) as? T
}
}
@objc extension NSObject {
var test: String {
get {
getAssociated(key: #selector(setter: self.test)) ?? ""
}
set {
setAssociated(key: #selector(setter: test), value: newValue, policy: .OBJC_ASSOCIATION_COPY_NONATOMIC)
}
}
var test1: String {
get {
getAssociated(key: #selector(setter: self.test1)) ?? ""
}
set {
setAssociated(key: #selector(setter: test1), value: newValue, policy: .OBJC_ASSOCIATION_COPY_NONATOMIC)
}
}
}
do {
let obj = NSObject()
obj.test = "123"
obj.test1 = "789"
print(obj.test)
print(obj.test1)
}
do {
let obj = NSObject()
obj.test = "456"
obj.test1 = "000"
print(obj.test)
print(obj.test1)
}
do {
let obj = NSObject()
obj.test = "999"
obj.test1 = "555"
print(obj.test)
print(obj.test1)
}
do {
let p = unsafeBitCast(#selector(setter: NSObject.test), to: UnsafeRawPointer.self)
print(#function, p)
}
do {
let p = unsafeBitCast(#selector(setter: NSObject.test), to: UnsafeRawPointer.self)
print(#function, p)
}
do {
let p = unsafeBitCast(#selector(setter: NSObject.test), to: UnsafeRawPointer.self)
print(#function, p)
}
do {
let p = unsafeBitCast(#selector(getter: NSObject.test), to: UnsafeRawPointer.self)
print(#function, p)
}
do {
let p = unsafeBitCast(#selector(setter: NSObject.test1), to: UnsafeRawPointer.self)
print(#function, p)
}
do {
let p = unsafeBitCast(#selector(getter: NSObject.test1), to: UnsafeRawPointer.self)
print(#function, p)
}
第二种改进写法 - 利用协议
protocol AssociatedObject {}
extension AssociatedObject {
func setAssociated(key: Selector, value: Any?, policy: objc_AssociationPolicy) {
let p = unsafeBitCast(key, to: UnsafeRawPointer.self)
objc_setAssociatedObject(self, p, value, policy)
}
func getAssociated<T>(key: Selector) -> T? {
let p = unsafeBitCast(key, to: UnsafeRawPointer.self)
return objc_getAssociatedObject(self, p) as? T
}
}
class Test {}
@objc extension Test: AssociatedObject {
var test: String {
get {
getAssociated(key: #selector(setter: self.test)) ?? ""
}
set {
setAssociated(key: #selector(setter: test), value: newValue, policy: .OBJC_ASSOCIATION_COPY_NONATOMIC)
}
}
var test1: String {
get {
getAssociated(key: #selector(setter: self.test1)) ?? ""
}
set {
setAssociated(key: #selector(setter: test1), value: newValue, policy: .OBJC_ASSOCIATION_COPY_NONATOMIC)
}
}
}
网友评论