網站首頁 編程語言 正文
正文
我們平時用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
,讓我們的功能更清晰
原文鏈接:https://juejin.cn/post/7142661331458457613
相關推薦
- 2022-10-19 Pandas如何對Categorical類型字段數據統計實戰案例_python
- 2024-02-29 UNI-APP開發之插件安裝失敗,離線安裝
- 2022-10-19 C++模板編程特性之移動語義_C 語言
- 2022-05-20 python使用數字與字符串方法技巧_python
- 2022-10-27 Apache?Hive?通用調優featch抓取機制?mr本地模式_Linux
- 2023-01-08 Android消息機制原理深入分析_Android
- 2022-09-22 Mybaits一級緩存和二級緩存分別是什么,區別是什么?
- 2022-12-11 Go?模塊在下游服務抖動恢復后CPU占用無法恢復原因_Golang
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支