我正在尝试创建一个实用程序,将闭包添加为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)在调用返回可选API的情况下,这两个if语句看起来都很难看;如果它是零,我想用一些默认的方法覆盖它,那么我必须强制展开它。有没有一种更地道的“更快”的方法来做到这一点?
2)另外,当我创建一个包含一个键值对int到闭包的closureDict时,我使用setAssociatedObject存储它,然后在getAssociatedObject中检索回什么,我会得到一个带有0键值对的字典。怎么一回事?这是个问题,因为我的closureWrapper没有被保留,而且整个事情都不起作用
发布于 2015-09-25 16:01:58
您可以简化行:
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)问题是Set是一个struct,与class不同,它不是一个“引用”类型。因此,var closures = ...行正在创建一个新的Set<ClosureWrapper>副本,而不是引用原始副本。因此,您正在更新Set<ClosureWrapper>的副本,而不是引用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)
}https://stackoverflow.com/questions/32785162
复制相似问题