文章

Swift泛型学习

泛型的使用

参考文章和资料

https://juejin.cn/post/6844904201839984648 理论介绍

https://github.com/JoanKing/JKSwiftExtension Swift常用扩展、组件(链式调用)、协议,方便项目快速搭建

巧妙用法

泛型的约束

1
2
// `T`约束为继承自`SomeClass`的类型 `U`约束为遵守`SomeProtocol` 协议的类型
func someFunction<T: SomeClass, U: SomeProtocol>(someT: T, someU: U) {}

泛型的where闭包

1
2
3
4
5
6
// where用法,是个条件判断,之前理解 `:`是表示需要实现UIButton的协议的Base才行,实际上还表示继承自UIButton的才行
public extension JKPOP where Base: UIButton {}

// 可以要求Base未UIButton的特定类型
public extension JKPOP where Base == UIButton {}

类型关联

关联类型使用关键字associatedtype指定。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// 定义实现Base泛型的JKPOP的结构体
public struct JKPOP<Base> {
    let base: Base
    init(_ base: Base) {
        self.base = base
    }
}

public protocol JKPOPCompatible {}
// 添加JKPOPCompatible,以便后面扩展实现链式函数
public extension JKPOPCompatible {
    static var jk: JKPOP<Self>.Type {
        get{ JKPOP<Self>.self }
        set {}
    }
    
    var jk: JKPOP<Self> {
        get { JKPOP(self) }
        set {}
    }
}

/// Define Property protocol
internal protocol JKSwiftPropertyCompatible {
  
    /// Extended type
    associatedtype T
    
    ///Alias for callback function
    typealias SwiftCallBack = ((T?) -> ())
    
    ///Define the calculated properties of the closure type
    var swiftCallBack: SwiftCallBack?  { get set }
}

Button的扩展

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// UIView和它的子类都添加JKPOPCompatible,这样可以通过.jk的形式调用JKPOP,将自己赋值给JKPOP中的base属性
extension UIView: JKPOPCompatible {}

private var buttonCallBackKey: Void?
extension UIButton: JKSwiftPropertyCompatible {
    internal typealias T = UIButton
    internal var swiftCallBack: SwiftCallBack? {
        get { return jk_getAssociatedObject(self, &buttonCallBackKey) }
        set { jk_setRetainedAssociatedObject(self, &buttonCallBackKey, newValue) }
    }
    
    @objc internal func swiftButtonAction(_ button: UIButton) {
        self.swiftCallBack?(button)
    }
}

// 对UIButton的能力进行JKPOP扩展
// 扩展JKPOP约束Base泛型必须是UIButton的类型
// 这样,对属性base的操作动作都是对button的操作
public extension JKPOP where Base: UIButton {
    
    // MARK: 5.1、button的事件
    /// button的事件
    /// - Parameters:
    ///   - controlEvents: 事件类型,默认是 valueChanged
    ///   - buttonCallBack: 事件
    /// - Returns: 闭包事件
    func setHandleClick(controlEvents: UIControl.Event = .touchUpInside, buttonCallBack: ((_ button: UIButton?) -> ())?){
        base.swiftCallBack = buttonCallBack
        base.addTarget(base, action: #selector(base.swiftButtonAction), for: controlEvents)
    }
}
本文由作者按照 CC BY 4.0 进行授权