前语
我报名参加金石计划1期应战——分割10万奖池,这是我的第1篇文章,点击查看活动详情
咱们平时用swift
写第三方扩展(OC中的分类)时,可能会直接就往扩展里边写办法,简略又便利,然而当咱们看一些常用你的三方(例如:Kingfisher、SnapKit
)等,都会用一个简略的参数引出(例如:kf
、snp
),下面来探索一下怎样用的,然后在总结其优缺点
SnapKit扩展办法扼要考虑
以 SnapKit
为例,运用如下,发现引进了 snp
var iv = UIImageView();
iv.snp.makeConstraints { make in
}
中心变量 snp
如下所示,ConstraintView
是一致不同渠道的重命名(别号)
public extension ConstraintView {
var snp: ConstraintViewDSL {
return ConstraintViewDSL(view: self)
}
}
其曾经版别也是直接将 left
等加上前缀 snp_
,直接调用,而参加前缀我想咱们一眼就看出来意图了,没错避免与其他扩展重名,现在也已经改成了引进snp
的办法,来直接调用,实践逻辑都经过 snp
来调用,个人猜想也是学习了主流的应用来更新的,调用时,至少分类 API 整洁了
优缺点
:
- 1、引进中心变量
snp
之后,首要感觉到的便是,咱们的分类在调用的时分,显着没有那么多杂乱的办法了(这种办法OC其实也能够学习) - 2、别的也能够取消了
前缀
,减少了代码量,并且当与其他类呈现重名的时分,只需要替换snp
的变量姓名即可,不需要替换悉数
办法,减少了命名阻止 - 3、不同三方之间经过引进该参数,让咱们的调用模块标识更显着,功用模块也更明晰,可维护性更强
Kingfisher扩展办法扼要考虑
以 Kingfisher
为例,运用如下,发现引进了 kf
var iv = UIImageView();
iv.kf.setImage(with: URL(string: "http://www.baidu.com"))
别的其在运用过程中,经过充分利用 swift
特性,比 SnapKit
运用上更高雅高效一些
//声明一个根底协议,有必要为 AnyObject 类型,可用于后续给根底类添加协议
public protocol KingfisherCompatible: AnyObject { }
//扩展实现该根底协议,以便于便利让咱们的组件能够直接经过 .kf 直接调用里边的办法
//此 kf 和 snap 相似,只不过添加了一个泛型,用于不同类之间进行扩展约束
extension KingfisherCompatible {
public var kf: KingfisherWrapper<Self> {
get { return KingfisherWrapper(self) }
set { }
}
}
//经过泛型顶一个一个根底类,经过该根底类能够获取咱们被扩展的组件
//且经过该根底类的泛型,能够分别给不同类型添加不同扩展办法
public struct KingfisherWrapper<Base> {
public let base: Base
public init(_ base: Base) {
self.base = base
}
}
//当遵从协议的类为 UIImage 的时分,为其扩展办法
extension KingfisherWrapper where Base: KFCrossPlatformImage {
...
}
//当遵从协议的类为 KFCrossPlatformImageView 的时分,为其扩展办法
extension KingfisherWrapper where Base: KFCrossPlatformImageView {
...
}
...
//上面仅仅是界说了一个扩展后能够运用的协议,并未应用到咱们的根底组件中
//因此只需要给根底组件添加扩展,遵从咱们的协议即可
extension KFCrossPlatformImageView: KingfisherCompatible { }
没见到姓名的View 是为了不同渠道一致姓名起的别号,如下所示(消除疑虑专用)
#if os(iOS) || os(tvOS)
public typealias ConstraintView = UIView
#else
public typealias ConstraintView = NSView
#endif
优缺点:
- 1、引进中心变量
kf
之后,首要感觉到的便是,咱们的分类在调用的时分,显着没有那么多杂乱的办法了(这种办法OC其实也能够学习) - 2、别的也能够取消了
前缀
,减少了代码量,并且当与其他类呈现重名的时分,只需要替换kf
的变量姓名即可,不需要替换悉数
办法,减少了命名阻止 - 3、不同三方之间经过引进该参数,让咱们的调用模块标识更显着,功用模块也更明晰,可维护性更强
- 4、引进协议和泛型,经过协议一致引进同一个中心变量,经过泛型给不同的分类扩展出不同的办法,减少无效办法和代码等,结构更明晰,某种角度上,其为进阶版的扩展办法
自行仿照尝试
public protocol MarshalTest: AnyObject {}
struct Wrapper<T> {
public let base: T
init(_ base: T) {
self.base = base
}
}
extension MarshalTest {
var ml: Wrapper<Self> {
get { Wrapper(self) }
set { }
}
}
extension UIImageView : MarshalTest {}
extension Wrapper where T: UIImageView {
func setImg() {
}
}
extension Wrapper where T: UIView {
func setBkg() {
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
var iv2 = UIImageView()
iv2.ml.setImg()
}
}
这就测试成功了,咱们仿照时,就能够参考这个写
最终
当咱们自己为默认组件扩展内容时,假如只扩展一个类和功用,能够像 snp
相同,直接引进中心变量扩展即可,假如咱们的扩展了多个分类,而隶属于一个模块,那么能够仿照 Kingfisher
,让咱们的功用更明晰