Swift扩展存储属性
Swift默认只能扩展计算属性无法扩展存储属性,如果想扩展存储属性就需要使用runtime。
使用runtime的两个核心方法(关联对象)
/// 设置值
/// - 参数1: 为哪个对象设置 参数2: 属性的指针地址(&+属性) 参数3: 属性的值 参数4:属性的修饰类型枚举值(可以理解为OC 属性关键字weak、copy等)
public func objc_setAssociatedObject(_ object: Any, _ key: UnsafeRawPointer, _ value: Any?, _ policy: objc_AssociationPolicy)
/// 获取值
/// - 参数1: 从哪个对象中获取 参数2:获取给属性的地址
public func objc_getAssociatedObject(_ object: Any, _ key: UnsafeRawPointer) -> Any?
policy的值枚举
public enum objc_AssociationPolicy : UInt {
/// weak
/**< Specifies a weak reference to the associated object. */
case OBJC_ASSOCIATION_ASSIGN
/// retain nonatomic (一般使用这个)
/**< Specifies a strong reference to the associated object.
* The association is not made atomically. */
case OBJC_ASSOCIATION_RETAIN_NONATOMIC
/// copy nonatomic
/**< Specifies that the associated object is copied.
* The association is not made atomically. */
case OBJC_ASSOCIATION_COPY_NONATOMIC
/// retain
/**< Specifies a strong reference to the associated object.
* The association is made atomically. */
case OBJC_ASSOCIATION_RETAIN
/// copy
/**< Specifies that the associated object is copied.
* The association is made atomically. */
case OBJC_ASSOCIATION_COPY
}
示例:为UIViewController添加导航栏透明度和颜色存储属性
通过使用私有结构体静态变量属性、扩展计算属性和runtime赋值获取实行swift扩展存储属性
/// 假如给每个Controller 添加两个存储属性 记录导航栏透明度和颜色
extension UIViewController {
/// 使用 私 结构体 并设置静态变量属性 作为存储
fileprivate struct AssociatedKeys {
static var navBarAlpha: CGFloat = 1.0
static var navBarColor: UIColor = UIColor.white
}
/// 再使用计算属性的方式 保存
open var navBarBgAlpha: CGFloat {
get {
guard let alpha = objc_getAssociatedObject(self, &AssociatedKeys.navBarAlpha) as? CGFloat else {
return 1.0
}
return alpha
}
set {
let alpha = max(min(newValue, 1), 0) // 必须在 0~1的范围
// 属性修饰关键字 retain nonatomic
objc_setAssociatedObject(self, &AssociatedKeys.navBarAlpha, alpha, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
open var navBarTintColor: UIColor {
get {
guard let tintColor = objc_getAssociatedObject(self, &AssociatedKeys.navBarColor) as? UIColor else {
return .white
}
return tintColor
}
set {
navigationController?.navigationBar.tintColor = newValue
objc_setAssociatedObject(self, &AssociatedKeys.navBarColor, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
}
扩展添加runtime替换方法
注意:OC中的+load 和+initlaze方法在Swift4之后都不可以用了,所以只用通过在扩展 类方法中实现方法交换,然后在应用启动的didFinishLaunch中调用。
【链接参考】