【问题标题】:Interacting with objective c associated object storage from swift从swift与objective c关联的对象存储进行交互
【发布时间】:2023-03-20 02:38:01
【问题描述】:

我正在尝试创建一个实用程序来添加闭包作为 UIControls 的事件处理程序,尽管我遇到了一些问题,这里是代码:

public func addCallBack(callback: Void -> Void, forControlEvents events: UIControlEvents)
{   
    var optClosureDict = objc_getAssociatedObject(self, &UIControlClosureDictKey) as? Dictionary<UInt, Set<ClosureWrapper>>

    if optClosureDict == nil {
        optClosureDict = Dictionary<UInt, Set<ClosureWrapper>>()
    }

    var closureDict = optClosureDict!

    if closureDict[events.rawValue] == nil {
        closureDict[events.rawValue] = Set<ClosureWrapper>()
    }

    var closures = closureDict[events.rawValue]!

    let wrapper = ClosureWrapper(callback:callback)
    addTarget(wrapper, action:"invoked", forControlEvents: events)
    closures.insert(wrapper)

    objc_setAssociatedObject(self, &UIControlClosureDictKey, optClosureDict!, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
    var res = objc_getAssociatedObject(self, &UIControlClosureDictKey) as? Dictionary<UInt, Set<ClosureWrapper>>
}

1) 两个 if 语句看起来都很难看,我调用了一个返回可选的 API,如果它是 nil,我想用一些默认值覆盖它,那么我必须强制解包它。有没有更惯用的“Swifter”方式来做到这一点?

2) 同样,当我创建一个具有一个 int 键值对的闭包字典时,我使用 setAssociatedObject 将其存储,然后我在 getAssociatedObject 中检索回来的内容,我得到一个包含 0 个键值对的字典。到底是怎么回事?这是一个问题,因为我的closureWrapper 没有被保留并且整个事情都没有工作

【问题讨论】:

    标签: objective-c swift


    【解决方案1】:

    你可以简化线条:

    var optClosureDict = objc_getAssociatedObject(self, &UIControlClosureDictKey) as? Dictionary<UInt, Set<ClosureWrapper>>
    
    if optClosureDict == nil {
        optClosureDict = Dictionary<UInt, Set<ClosureWrapper>>()
    }
    
    var closureDict = optClosureDict!
    

    var closureDict = objc_getAssociatedObject(self, &UIControlClosureDictKey) as? Dictionary<UInt, Set<ClosureWrapper>> ?? Dictionary<UInt, Set<ClosureWrapper>>()
    

    或者,您可以定义一个类型以使其更具可读性:

    typealias ClosureDict = [UInt : Set<ClosureWrapper>]
    

    然后那行变成:

    var closureDict = objc_getAssociatedObject(self, &UIControlClosureDictKey) as? ClosureDict ?? ClosureDict()
    

    --

    另外,下面的代码并没有达到你的预期:

    var closures = closureDict[events.rawValue]!
    
    let wrapper = ClosureWrapper(callback:callback)
    addTarget(wrapper, action:"invoked", forControlEvents: events)
    closures.insert(wrapper)
    

    问题在于Setstruct,与class 不同,它不是“引用”类型。所以var closures = ... 行正在制作Set&lt;ClosureWrapper&gt; 的新副本,而不是引用原始副本。因此,您正在更新Set&lt;ClosureWrapper&gt; 的副本,而不是引用closureDict 中的副本。

    您可以在完成后更新closureDict

    var closures = closureDict[events.rawValue]!
    
    let wrapper = ClosureWrapper(callback:callback)
    addTarget(wrapper, action:"invoked", forControlEvents: events)
    closures.insert(wrapper)
    
    closureDict[events.rawValue] = closures
    

    或者更简单地说,就地更新它:

    let wrapper = ClosureWrapper(callback:callback)
    addTarget(wrapper, action:"invoked", forControlEvents: events)
    closureDict[events.rawValue]!.insert(wrapper)
    

    --

    因此这会产生以下替代方案:

    func addCallBack(callback: Void -> Void, forControlEvents events: UIControlEvents) {
        var closureDict = objc_getAssociatedObject(self, &UIControlClosureDictKey) as? ClosureDict ?? ClosureDict()
    
        if closureDict[events.rawValue] == nil {
            closureDict[events.rawValue] = Set<ClosureWrapper>()
        }
    
        let wrapper = ClosureWrapper(callback:callback)
        addTarget(wrapper, action:"invoked", forControlEvents: events)
        closureDict[events.rawValue]!.insert(wrapper)
    
        objc_setAssociatedObject(self, &UIControlClosureDictKey, closureDict, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
    }
    

    func addCallBack(callback: Void -> Void, forControlEvents events: UIControlEvents) {
        var closureDict = objc_getAssociatedObject(self, &UIControlClosureDictKey) as? ClosureDict ?? ClosureDict()
    
        var closures = closureDict[events.rawValue] ?? Set<ClosureWrapper>()
    
        let wrapper = ClosureWrapper(callback:callback)
        addTarget(wrapper, action:"invoked", forControlEvents: events)
        closures.insert(wrapper)
    
        closureDict[events.rawValue] = closures
    
        objc_setAssociatedObject(self, &UIControlClosureDictKey, closureDict, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
    }
    

    【讨论】:

    • 谢谢你的回答很精彩
    猜你喜欢
    • 1970-01-01
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-13
    • 2012-11-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多