介紹
比如寫一個(gè) lg
為后綴的命名空間少漆,類似于 RxSwift
中的 rx
, Kingfisher
中的 kf
撑刺,可用以區(qū)別和添加 lg
獨(dú)有的擴(kuò)展方法。
Lg.swift
中實(shí)現(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)建一個(gè)
LgWrapper
的對(duì)象,它就像一個(gè)容器,里面會(huì)包含一個(gè)泛型對(duì)象 base痹栖,實(shí)際上真正做事的是這個(gè) base 對(duì)象。寫一個(gè)
LgCompatible
空協(xié)議瞭空,默認(rèn)為它添加一個(gè)
lg
屬性结耀,這樣一來(lái),只要我想為某對(duì)象A 添加lg
命名空間匙铡,就只需要讓A
遵守LgCompatible
協(xié)議:extension A: LgCompatible {}
,就可以讓a
擁有a.lg
屬性碍粥。該
lg
屬性返回的是一個(gè) 包裹了 a對(duì)象 的 LgWrapper<A> 對(duì)象鳖眼。假設(shè)A擁有一個(gè)方法
doSomething()
,那么嚼摩,為LgWrapper
寫一個(gè)擴(kuò)展方法doSomething()
钦讳,就可以在其中調(diào)用base.doSomething()
方法了。
用法:
若對(duì)象 A
想擴(kuò)展 lg
命名空間枕面,
已知:
class A {
func doSomething() {
print("doSomething")
}
}
做法如下:
// 在文件 Lg.swift 中為控件 A 實(shí)現(xiàn)命名空間的協(xié)議(內(nèi)容是空的)
extension A: LgCompatible {}
// 在你自己的文件中愿卒,實(shí)現(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頂部會(huì)留部分距離是有暗色半透明背景。
但是項(xiàng)目中暫不需要這樣的風(fēng)格枕荞,所以在 Lg+UIViewController.swift
文件中柜候,以 lg
為命名空間 對(duì) 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)
}
}
使用的時(shí)候加上 .lg.present
:
viewController.lg.present(vc2, animated: true, completion: nil)