介紹
比如寫一個 lg 為后綴的命名空間,類似于 RxSwift 中的 rx, Kingfisher 中的 kf,可用以區(qū)別和添加 lg 獨有的擴(kuò)展方法。
Lg.swift 中實現(xiàn) lg 命名空間的代碼如下:
public struct LgWrapper<Base> {
public let base: Base
public init(_ base: Base) {
self.base = base
}
}
public protocol LgCompatible {}
extension LgCompatible {
public var lg: LgWrapper<Self> {
get { return LgWrapper(self) }
set {}
}
}
思路:
創(chuàng)建一個
LgWrapper的對象,它就像一個容器,里面會包含一個泛型對象 base,實際上真正做事的是這個 base 對象。寫一個
LgCompatible空協(xié)議,默認(rèn)為它添加一個
lg屬性,這樣一來,只要我想為某對象A 添加lg命名空間,就只需要讓A遵守LgCompatible協(xié)議:extension A: LgCompatible {},就可以讓a擁有a.lg屬性。該
lg屬性返回的是一個 包裹了 a對象 的 LgWrapper<A> 對象。假設(shè)A擁有一個方法
doSomething(),那么,為LgWrapper寫一個擴(kuò)展方法doSomething(),就可以在其中調(diào)用base.doSomething()方法了。
用法:
若對象 A 想擴(kuò)展 lg 命名空間,
已知:
class A {
func doSomething() {
print("doSomething")
}
}
做法如下:
// 在文件 Lg.swift 中為控件 A 實現(xiàn)命名空間的協(xié)議(內(nèi)容是空的)
extension A: LgCompatible {}
// 在你自己的文件中,實現(xiàn)具體需要的方法
extension LgWrapper where Base: A {
func doSomething() {
base.doSomething()
}
}
使用:
let a = A()
a.doSomething()
示例:
例如,在 iOS 13 之后,系統(tǒng)默認(rèn)的 present方法使用 modalPresentationStyle = .pageSheet 樣式彈出,即彈出的 ViewController頂部會留部分距離是有暗色半透明背景。
但是項目中暫不需要這樣的風(fēng)格,所以在 Lg+UIViewController.swift 文件中,以 lg 為命名空間 對 UIViewController 進(jìn)行擴(kuò)展,代碼如下:
extension LgWrapper where Base: UIViewController {
func present(_ viewController: UIViewController, presentationStyle: UIModalPresentationStyle = .fullScreen, animated: Bool, completion: (() -> Void)? = nil) {
if viewController.modalPresentationStyle == .pageSheet {
viewController.modalPresentationStyle = presentationStyle
}
base.present(viewController, animated: animated, completion: completion)
}
}
使用的時候加上 .lg.present:
viewController.lg.present(vc2, animated: true, completion: nil)