在开发中,经常能碰到需要给不同status设置不同的 backgroundColor 或者 borderColor ,如果新建一个子类的话可能会很麻烦,这时候,如果用 extension 仿照 setTitleColor 的方法新写一个 setBackGroundColor 的方法封装一下就感觉很惬意了,话不多说,上代码:
先设置对外接口
open func setBackgroudColor(_ color: UIColor, for state: UIControlState) {
backGroundColorsForStates[state.rawValue] = color
onStateChanged()
}
open func setBoarderColor(_ color: UIColor, for state: UIControlState) {
boarderColorsForStates[state.rawValue] = color
onStateChanged()
}
这时候出现了 boarderColorsForStates 属性和 onStateChanged 方法,status 绑定的 backGroundColor 需要存储到某个属性中,而 extension 是无法添加属性的,此时我们只好用简单的运行时方法,给 UIButton 添加一个简单的键值对属性,即
private var boarderColorsForStates: [UInt: UIColor] {
get {
return (objc_getAssociatedObject(self, &UIButtonObjectKeys.boarderColorsForStates) as? [UInt: UIColor]) ?? [UInt: UIColor]()
}
set {
objc_setAssociatedObject(self, &UIButtonObjectKeys.boarderColorsForStates, newValue, .OBJC_ASSOCIATION_RETAIN)
}
}
private var backGroundColorsForStates: [UInt: UIColor] {
get {
return (objc_getAssociatedObject(self, &UIButtonObjectKeys.backGroundColorsForStates) as? [UInt: UIColor]) ?? [UInt: UIColor]()
}
set {
objc_setAssociatedObject(self, &UIButtonObjectKeys.backGroundColorsForStates, newValue, .OBJC_ASSOCIATION_RETAIN)
}
}
swift 中动态添加属性的 key 需要时 UnsafeRawPointer 格式的,UnsafeRawPointer 格式也就是类似于 OC 中的指针,即取 String 的指针作为 key 传过去。
而 onStateChanged() 是在 UIButton status 状态改变时传作一些操作,例如设置 status 对应的 backGroundColor,即:
private func onStateChanged() {
if let color = self.backGroundColorsForStates[self.state.rawValue] {
self.backgroundColor = color
} else if let color = self.backGroundColorsForStates[UIControlState.normal.rawValue] {
self.backgroundColor = color
}
if let color = self.boarderColorsForStates[self.state.rawValue] {
self.borderColor = color
} else if let color = self.boarderColorsForStates[UIControlState.normal.rawValue] {
self.borderColor = color
}
}
同样的,在设置 selected、highlighted、enabled 时也要调用这个方法,即重写这三个值的 set 方法和 get 方法:
override open var isSelected: Bool {
get {
return super.isSelected
}
set {
if newValue != isSelected {
super.isSelected = newValue
onStateChanged()
}
}
}
override open var isHighlighted: Bool {
get {
return super.isHighlighted
}
set {
super.isHighlighted = newValue
onStateChanged()
}
}
override open var isEnabled: Bool {
get {
return super.isEnabled
}
set {
if newValue != isSelected {
super.isEnabled = newValue
onStateChanged()
}
}
}
到这里,添加的这个 extension 就算大功告成了,你可以尝试给 UIButton 设置不同 status 下的 backGroundColor 等属性
网友评论