您好,登錄后才能下訂單哦!
這篇文章主要介紹“iOS Lotusoot模塊化工具如何應用”,在日常操作中,相信很多人在iOS Lotusoot模塊化工具如何應用問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”iOS Lotusoot模塊化工具如何應用”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
個人覺得
例如,URL 路由的注冊,就是把約定的信息,傳過去。作為服務。
Lotusoot 包含服務調(diào)用,短鏈的注冊與調(diào)用
下面著重講服務調(diào)用,短鏈略
project 有兩個依賴 A (協(xié)議) 和 B (協(xié)議的實現(xiàn)者,提供服務)
project 引用 A,知道了協(xié)議信息
project 不引用 B , project 對 B 一無所知
這樣 project 把 B 去掉,編譯的更快
B 依賴 A, 引用 A, 實現(xiàn) A 的協(xié)議,提供服務
// 拿到 key let lotus = s(AccountLotus.self) // kv 取得提供服務的實例 let accountModule: AccountLotus = LotusootCoordinator.lotusoot(lotus: lotus) as! AccountLotus // 調(diào)用服務 accountModule.login(username: "zhoulingyu", password: "wow") { (error) in print(error ?? "1234") }
第 3 步,調(diào)用服務很簡單
第 2 步,挺精彩,充分使用了 Swift 編譯時的靜態(tài)特性
協(xié)議的方法,編譯時確定了
需要幾個參數(shù),啥類型的,一般都可以顯式使用
不用看到一個參數(shù)字典,啊,這是啥
// 第 2 步。從下面取 // 鍵值對,值是提供服務的對象 var lotusootMap: Dictionary = Dictionary<String, Any>()
第 1 步, 拿到鍵
這里把協(xié)議名,作為 key
// 使用泛型,取其描述 // 協(xié)議,轉協(xié)議名 public extension String { init<Subject>(_ instance: Subject) { self.init(describing: instance) } } /// 通過 Subject 快速獲取字符串 public func s<Subject>(_ instance: Subject) -> String { return String(instance) }
1, Project 沒有 import B ( 提供服務 ), 怎么使用 B 的功能?
public static func registerAll(serviceMap: Dictionary<String, String>) { for (lotus, lotusootName) in serviceMap { // lotus, 協(xié)議名 // lotusootName, 包名.類名 let classStringName = lotusootName // 反射,產(chǎn)生類 // 提供服務的類,一定是 NSObject 的子類,擁有 init 方法 ( 這是個約定 ) let classType = NSClassFromString(classStringName) as? NSObject.Type if let type = classType { // 產(chǎn)生對應的實例,強轉為遵守協(xié)議的 ,即可 let lotusoot = type.init() register(lotusoot: lotusoot, lotusName: lotus) } } }
2, 這里使用 python 腳本注冊,編譯的時候拿到信息 協(xié)議名:包名.類名
通過約定, 標記
// @NameSpace(ZLYAccountModule) // @Lotusoot(AccountLotusoot) // @Lotus(AccountLotus) class AccountLotusoot: NSObject, AccountLotus {}
python 腳本找出標記,整合,放入 plist
文件中
1, 腳本入口
lotusootSuffix = 'Lotusoot' length = len(sys.argv) if length != 3 and length != 4: print 'parameter error' os._exit(1) if length == 4: lotusootSuffix = sys.argv[3] lotusootFiles = findLotusoots(scanPath, lotusootSuffix + '.swift') else: // 走這里 lotusootFiles = findAmbiguityLotusoots(scanPath)
翻閱每一個 swift 文件
def findAmbiguityLotusoots(path): list = [] for root, subFolders, files in os.walk(path): # Ignore 'Target Support Files' and 'Pods.xcodeproj' // 不需要處理的,不處理 if 'Target Support Files' in subFolders: subFolders.remove('Target Support Files') // 不需要處理的,略 if 'Pods.xcodeproj' in subFolders: subFolders.remove('Pods.xcodeproj') // 每一個文件 for f in files: // 每一個 Swift 文件 if f.endswith('.swift'): // 獲取標記的配置 tup = getLotusootConfig(os.path.join(root, f)) if tup[0] and tup[1] and tup[2]: // 三者都滿足,把文件路徑,給添加了 list.append(f) return list
掃描每一行,
獲取配置,上面看到的包名,命名空間
@NameSpace(ZLYAccountModule)
上面看到的類名
@Lotusoot(AccountLotusoot)
上面看到的 key ( 協(xié)議名 )
@Lotus(AccountLotus)
def getLotusootConfig(file): lotus = '' lotusoot = '' namespace = '' // 翻閱,文件的每一行 for line in open(file): // 上面看到的 key if getLotus(line): lotus = getLotus(line) // 上面看到的類名 if getLotusoot(line): lotusoot = getLotusoot(line) // 上面看到的包名,命名空間 if getNameSpace(line): namespace = getNameSpace(line) return (lotus, lotusoot, namespace)
… 還有好多,
邏輯是獲取配置,寫入一個 plist
運行的時候,啟動
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { LotusootCoordinator.registerAll() return true }
注冊就是,讀取剛才寫入的 plist, 作為 [協(xié)議名 : 包名.類名 ] 的字典,
@objc public static func registerAll() { let lotusPlistPath = Bundle.main.path(forResource: "Lotusoot", ofType: "plist") if let lotusPlistPath = lotusPlistPath { let map = NSDictionary(contentsOfFile: lotusPlistPath) registerAll(serviceMap: map as! Dictionary<String, String>) } }
與上文,相呼應
進入動態(tài)思路, 動態(tài)地注冊 KV ( 協(xié)議名: 服務庫名.類名)
上文有一個印象,知道場景,即可
寫文,當寫長,
怎樣體現(xiàn)我,10 年工作經(jīng)驗?
上文沒有,堅持湊字數(shù)
1,project 拿到 key (協(xié)議名) ,可以的
2,project 拿到所有的依賴信息
通過 MachO 可以
3,project 拿到服務類的名稱
確保 module B 的類名 = key ( 協(xié)議 ) + Cls
MachO
拿到所有依賴庫的名稱, 每一個 + “.” + key ( 協(xié)議 ) + Cls= MachO
拿到所有依賴庫的名稱, 每一個 + “.” + module B 的類名
然后,看能不能實例化,
能夠實例化,就 OK
試了一圈,不能夠實例化,就報錯
可能依賴 B, 沒有添加
可能依賴 B 的類名,寫錯了
project 拿到服務類的名稱, 優(yōu)雅的
確保 module B 的類名 = key ( 協(xié)議 ) + Cls,
硬編碼,是不好的
依賴 A ( 放協(xié)議的 ), 添加一個協(xié)議
public protocol Maid{ var name: String{ get } }
module B 里面,必須有一個叫 key (協(xié)議) + C 的類
該類,遵守 Maid
協(xié)議。
通過協(xié)議屬性,返回 B 中服務類的名稱
class AccountLotusC: NSObject, Maid{ var name: String{ return String(reflecting: AccountLotusoot.self) } }
這個過程,與上文模塊化利用協(xié)議的設計,比較一致
約定是,實現(xiàn)協(xié)議的服務模塊,
一定有一個 key + C 的類
提供服務類的名稱
硬編碼,比較輕微
import MachO lazy var moduleNames: [String] = { () -> [String] in // 找到 project 名稱,一會去除 let mainNameTmp = NSStringFromClass(LotusootCoordinator.self) guard let mainName = mainNameTmp.components(separatedBy: ".").first else{ fatalError("emptyMainProject") } var result = [String]() let cnt = _dyld_image_count() // 處理所有的包,系統(tǒng)的,用戶的 for i in 0..<cnt{ if let tmp = _dyld_get_image_name(i){ let name = String(validatingUTF8: tmp) // 系統(tǒng)的,不用管 if let candidate = name, candidate.hasPrefix("/Users"){ if let tmp = candidate.components(separatedBy: "/").last{ // 去除 project 的 if tmp != mainName{ // 拿到用戶依賴 result.append(tmp) } } } } } return result }()
以上,模擬器 OK, 真機沒試過 ( 手頭沒開發(fā)證書 )
@objc public static func lotusoot(lotus: String) -> Any? { // 已經(jīng)緩存了 if let val = sharedInstance.lotusootMap[lotus]{ return val } else{ var i = 0 let names = LotusootCoordinator.sharedInstance.moduleNames let cnt = names.count // 遍歷,用戶包 while i < cnt{ // 按照約定,嘗試制造助手類 let classType = NSClassFromString(names[i] + "." + lotus + "C") as? NSObject.Type if let type = classType { // 實例化,助手類 let assist = type.init() if let maid = assist as? Maid{ // 拿到 module B 的服務類的名稱 let classType = NSClassFromString(maid.name) as? NSObject.Type if let type = classType { // 將 module B 的服務類,實例化 let lotusoot = type.init() register(lotusoot: lotusoot, lotusName: lotus) } // 默認是,一個 module 一個服務類, // 排除掉,使用過的用戶類 LotusootCoordinator.sharedInstance.moduleNames.remove(at: i) break } } i+=1 } if let val = sharedInstance.lotusootMap[lotus]{ return val } else{ fatalError("name Module of" + lotus) } } }
到此,關于“iOS Lotusoot模塊化工具如何應用”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續(xù)學習更多相關知識,請繼續(xù)關注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。