Generics 将Swift对象与NSObject实例关联
我希望通过扩展将Swift事物(泛型、结构、元组、Objective-C不喜欢的任何东西)与NSObject实例关联起来 我们今天怎么能做到这一点Generics 将Swift对象与NSObject实例关联,generics,swift,nsobject,Generics,Swift,Nsobject,我希望通过扩展将Swift事物(泛型、结构、元组、Objective-C不喜欢的任何东西)与NSObject实例关联起来 我们今天怎么能做到这一点objc_setassociated object对于处理Swift功能没有任何用处 我的第一种方法是使用带有弱键的全局字典来存储关联。比如: struct WeakKey<T where T: NSObject> : Hashable { weak var object : T! init (object: T) {
objc_setassociated object
对于处理Swift功能没有任何用处
我的第一种方法是使用带有弱键的全局字典来存储关联。比如:
struct WeakKey<T where T: NSObject> : Hashable {
weak var object : T!
init (object: T) {
self.object = object
}
var hashValue: Int { return self.object.hashValue }
}
func ==<T where T: NSObject>(lhs: WeakKey<T>, rhs: WeakKey<T>) -> Bool {
return lhs.object == rhs.object
}
typealias ThingObjcDoesntLike = (Int, String)
var _associations : [WeakKey<NSObject>: ThingObjcDoesntLike] = [:]
extension NSObject {
var associatedThing : ThingObjcDoesntLike! {
get {
let key = WeakKey(object: self)
return _associations[key]
}
set(thing) {
let key = WeakKey(object: self)
_associations[key] = thing
}
}
}
let o = NSObject()
let t = (1, "Hello World")
o.associatedThing = t
struct WeakKey:Hashable{
弱var对象:T!
init(对象:T){
self.object=对象
}
var hashValue:Int{return self.object.hashValue}
}
func==(左:威基,右:威基)->Bool{
返回lhs.object==rhs.object
}
typealias ThingObjcDoesntLike=(Int,String)
变量关联:[WeakKey:ThingObjcDoesntLike]=[:]
扩展NSObject{
var AssociatedThingObjcDoesntlike{
得到{
让key=WeakKey(对象:self)
返回_关联[键]
}
设置(事物){
让key=WeakKey(对象:self)
_联想[关键]=事物
}
}
}
设o=NSObject()
设t=(1,“你好,世界”)
o、 关联事物=t
不幸的是,这会在\u关联
声明中的EXC\u BAD\u访问
时崩溃。删除弱
可以解决崩溃问题,但会导致保留NSObject实例
为了实现这一点,当NSObject被解除锁定时,我们还应将关联设置为
nil
。我们可以使用关联的见证对象进行此操作,并覆盖其解除锁定来完成此工作。为了简单起见,我在上面的代码中省略了这一点 像这样的东西怎么样:
class ObjectWrapper : NSObject {
let value: ThingObjcDoesntLike
init(value: ThingObjcDoesntLike) {
self.value = value
}
}
extension NSObject {
var associatedThing : ThingObjcDoesntLike! {
get {
let wrapper = objc_getAssociatedObject(self, someKey) as ObjectWrapper?
return wrapper?.value
}
set(value) {
let wrapper = ObjectWrapper(value: value)
objc_setAssociatedObject(self, someKey, wrapper, UInt(OBJC_ASSOCIATION_RETAIN_NONATOMIC))
}
}
}
@尼克洛克伍德的答案应该是正确的。然而,当使用他的方法时,我开始在运行时遇到奇怪的内存异常。这可能是另一回事,但当我尝试另一种方法时,问题消失了。我们必须进一步挖掘
以下是我在操场上的表现。我之所以发布它,是因为它看起来很有效,而且我觉得代码很有趣,即使它最终不是最好的解决方案
我正在使用一个全局Swift字典
,指针作为弱键。为了清除字典,我使用了一个与见证关联的对象,该对象通过deinit
上的关联回调该对象
import Foundation
import ObjectiveC
var _associations : [COpaquePointer: Any] = [:]
@objc protocol HasAssociatedSwift : class {
func clearSwiftAssociations()
}
var _DeinitWitnessKey: UInt8 = 0
class DeinitWitness : NSObject {
weak var object : HasAssociatedSwift!
init (object: HasAssociatedSwift) {
self.object = object
}
deinit {
object.clearSwiftAssociations()
}
class func addToObject(object : NSObject) {
var witness = objc_getAssociatedObject(object, &_DeinitWitnessKey) as DeinitWitness?
if (witness == nil) {
witness = DeinitWitness(object: object)
objc_setAssociatedObject(object, &_DeinitWitnessKey, witness, UInt(OBJC_ASSOCIATION_RETAIN_NONATOMIC))
}
}
}
extension NSObject : HasAssociatedSwift {
var associatedThing : Any! {
get {
return _associations[self.opaquePointer]
}
set(thing) {
DeinitWitness.addToObject(self)
_associations[self.opaquePointer] = thing
}
}
var opaquePointer : COpaquePointer {
return Unmanaged<AnyObject>.passUnretained(self).toOpaque()
}
func clearSwiftAssociations() {
_associations[self.opaquePointer] = nil
}
}
let o = NSObject()
o.associatedThing = (1, "Hello")
<代码>导入基础
导入对象
变量关联:[COpaquePointer:Any]=[:]
@objc协议已关联SWIFT:类{
func清除WiftAssociations()
}
var_DenithWitnessKey:UInt8=0
类DenitWitness:NSObject{
弱变量对象:hassociatedSwift!
init(对象:HasAssociatedSwift){
self.object=对象
}
脱硝{
object.ClearWiftAssociations()
}
类func addToObject(对象:NSObject){
var-witness=objc_getAssociatedObject(对象,&_DeinitWitnessKey)作为DeinitWitness?
如果(证人==无){
见证=取消见证(对象:对象)
objc_setAssociatedObject(对象和DeinitWitnessKey、见证、UInt(objc_关联、保留、非原子))
}
}
}
扩展NSObject:HasAssociatedSwift{
var associatedThing:任何{
得到{
返回关联[self.opaquePointer]
}
设置(事物){
DeinitWitness.addToObject(自)
_联想[self.opaquePointer]=事物
}
}
变量opaquePointer:COpaquePointer{
返回未托管的.passUnretained(self).toOpaque()
}
func清除WiftAssociations(){
_关联[self.opaquePointer]=nil
}
}
设o=NSObject()
o、 associatedThing=(1,“你好”)
谢谢你,尼克!这似乎是可行的,但是有没有保证
objc_setassociated object
可以正确处理和管理包装的纯Swift构造(超级结构、泛型等)的内存?不必。它只担心保留/释放容器对象(遵循正常的objc约定)。容器管理其内部构造的内存。它似乎比它看起来更重要。当使用这个时,我开始出现奇怪的内存错误。我最后做了一些我稍后会发布的事情。ObjectWrapper
不需要子类NSObject
@newacct一点也不需要,您只需要让ObjectWrapper接受泛型类型