<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
下文,寫的是 Swift 依賴
OC 庫,沒有名稱空間
個人覺得
例如,URL 路由的註冊,就是把約定的資訊,傳過去。作為服務。
Lotusoot 包含服務呼叫,短鏈的註冊與呼叫
下面著重講服務呼叫,短鏈略
project 有兩個依賴 A (協定) 和 B (協定的實現者,提供服務)
project 參照 A,知道了協定資訊
project 不參照 B , project 對 B 一無所知
這樣 project 把 B 去掉,編譯的更快
B 依賴 A, 參照 A, 實現 A 的協定,提供服務
// 拿到 key let lotus = s(AccountLotus.self) // kv 取得提供服務的範例 let accountModule: AccountLotus = LotusootCoordinator.lotusoot(lotus: lotus) as! AccountLotus // 呼叫服務 accountModule.login(username: "zhoulingyu", password: "wow") { (error) in print(error ?? "1234") }
第 3 步,呼叫服務很簡單
第 2 步,挺精彩,充分使用了 Swift 編譯時的靜態特性
協定的方法,編譯時確定了
需要幾個引數,啥型別的,一般都可以顯式使用
不用看到一個引數字典,啊,這是啥
// 第 2 步。從下面取 // 鍵值對,值是提供服務的物件 var lotusootMap: Dictionary = Dictionary<String, Any>()
第 1 步, 拿到鍵
這裡把協定名,作為 key
// 使用泛型,取其描述 // 協定,轉協定名 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, 協定名 // lotusootName, 包名.類名 let classStringName = lotusootName // 反射,產生類 // 提供服務的類,一定是 NSObject 的子類,擁有 init 方法 ( 這是個約定 ) let classType = NSClassFromString(classStringName) as? NSObject.Type if let type = classType { // 產生對應的範例,強轉為遵守協定的 ,即可 let lotusoot = type.init() register(lotusoot: lotusoot, lotusName: lotus) } } }
2, 這裡使用 python 指令碼註冊,編譯的時候拿到資訊 協定名:包名.類名
通過約定, 標記
// @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 ( 協定名 )
@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, 作為 [協定名 : 包名.類名 ] 的字典,
@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>) } }
與上文,相呼應
進入動態思路, 動態地註冊 KV ( 協定名: 服務庫名.類名)
上文有一個印象,知道場景,即可
寫文,當寫長,
怎樣體現我,10 年工作經驗?
上文沒有,堅持湊字數
1,project 拿到 key (協定名) ,可以的
2,project 拿到所有的依賴資訊
通過 MachO 可以
3,project 拿到服務類的名稱
確保 module B 的類名 = key ( 協定 ) + Cls
MachO
拿到所有依賴庫的名稱, 每一個 + “.” + key ( 協定 ) + Cls= MachO
拿到所有依賴庫的名稱, 每一個 + “.” + module B 的類名
然後,看能不能範例化,
能夠範例化,就 OK
試了一圈,不能夠範例化,就報錯
可能依賴 B, 沒有新增
可能依賴 B 的類名,寫錯了
project 拿到服務類的名稱, 優雅的
確保 module B 的類名 = key ( 協定 ) + Cls,
寫死,是不好的
依賴 A ( 放協定的 ), 新增一個協定
public protocol Maid{ var name: String{ get } }
module B 裡面,必須有一個叫 key (協定) + C 的類
該類,遵守 Maid
協定。
通過協定屬性,返回 B 中服務類的名稱
class AccountLotusC: NSObject, Maid{ var name: String{ return String(reflecting: AccountLotusoot.self) } }
這個過程,與上文模組化利用協定的設計,比較一致
約定是,實現協定的服務模組,
一定有一個 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() // 處理所有的包,系統的,使用者的 for i in 0..<cnt{ if let tmp = _dyld_get_image_name(i){ let name = String(validatingUTF8: tmp) // 系統的,不用管 if let candidate = name, candidate.hasPrefix("/Users"){ if let tmp = candidate.components(separatedBy: "/").last{ // 去除 project 的 if tmp != mainName{ // 拿到使用者依賴 result.append(tmp) } } } } } return result }()
以上,模擬器 OK, 真機沒試過 ( 手頭沒開發證書 )
@objc public static func lotusoot(lotus: String) -> Any? { // 已經快取了 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模組化工具應用的動態思路的文章就介紹到這了,更多相關iOS Lotusoot模組化內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45