Swift 扩展存储属性

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中调用。

链接参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值