成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

iOS 響應(yīng)式架構(gòu)設(shè)計方案

2021-10-14    分類: 網(wǎng)站建設(shè)

iOS 響應(yīng)式架構(gòu)設(shè)計方案
1.響應(yīng)式編程是一種和事件流有關(guān)的編程模式,關(guān)注導致狀態(tài)值改變的行為事件,一系列事件組成了事件流。
2.一系列事件是導致屬性值發(fā)生變化的原因。FRP非常類似于設(shè)計模式里的觀察者模式。

3.FRP與普通的函數(shù)式編程相似,但是每個函數(shù)可以接收一個輸入值的流,如果其中,一個新的輸入值到達的話,這個函數(shù)將根據(jù)最新的輸入值重新計算,并且產(chǎn)生一個新的輸出。這是一種”數(shù)據(jù)流”編程模式。


iOS 響應(yīng)式編程優(yōu)勢;
1,開發(fā)過程中,狀態(tài)以及狀態(tài)之間依賴過多,RAC更加有效率地處理事件流,而無需顯式去管理狀態(tài)。在OO或者過程式編程中,狀態(tài)變化是最難跟蹤,最頭痛的事。這個也是最重要的一點。
2, 減少變量的使用,由于它跟蹤狀態(tài)和值的變化,因此不需要再申明變量不斷地觀察狀態(tài)和更新值。
3, 提供統(tǒng)一的消息傳遞機制,將oc中的通知,action,KVO以及其它所有UIControl事件的變化都進行監(jiān)控,當變化發(fā)生時,就會傳遞事件和值。
4, 當值隨著事件變換時,可以使用map,filter,reduce等函數(shù)便利地對值進行變換操作。
設(shè)計一個簡單的 iOS 響應(yīng)式架構(gòu)。iOS 架構(gòu) DEMO
關(guān)于組件化;
組件化似乎是項目發(fā)展壯大過后必然要做的事情,它能讓各個業(yè)務(wù)線的工程師不需要過多的關(guān)注其他業(yè)務(wù)線的代碼,有效的提高團隊整體效率。然而實施組件化的時機是在需求相對穩(wěn)定、產(chǎn)品閉環(huán)形成過后。所以本文不會應(yīng)用組件化,但是這里簡單談?wù)剺I(yè)界的組件化方案。
組件化的核心問題就是組件間如何通訊?!败浖こ痰囊磺袉栴}都能通過一個間接的中間層解決。”中介模式很自然的運用起來:
這樣雖然能統(tǒng)一組件間的通訊請求,但是卻沒有避免 Mediator 和目標組件的耦合,ModuleA 工程中仍然需要導入 ModuleB
所以重點問題落在了解耦上:
要達到 Mediator 和目標組件的解耦,就需要實現(xiàn)它們之間的間接調(diào)用(圖中虛線),既然是間接調(diào)用,必然需要一種映射機制。在 iOS 開發(fā)中,業(yè)界大概有三種方式來處理。
(1) 使用 URL -> Block 解耦
簡單來說就是將組件的調(diào)用代碼放入 block 中,然后 URL 作為 key,block 作為 value,存入一個全局的 hash 容器,組件通過一個 URL (比如 “native/id=10/type=1” )向 Mediator 發(fā)起請求,Mediator 找到對應(yīng)的代碼塊執(zhí)行。由此,解開了 Mediator 和目標組件的耦合(見博客:蘑菇街 App 的組件化之路)。
這種方案的缺陷很多:組件越多常駐內(nèi)存越多;解析 URL 邏輯復(fù)雜;URL 無法表述具體語言相關(guān)的對象類型。所以這種方式并不適合組件化解耦。
(2) 使用 Protocol 解耦
阿里的 BeeHive 是該方案的很好實踐,筆者閱讀了一下源碼,它的大致工作原理如下:注冊 Protocol 對應(yīng)的組件,這個和上面說的 URL->Block 方式如出一轍,只不過這里是 Protocol-> Module ;組件申請訪問時導入對應(yīng)的 Protocol 通過 Mediator 獲取到對應(yīng)的組件對象。由于協(xié)議的表述能支持所有的對象類型,所以這種方式能基本解決組件間通信的需求。
BeeHive 注冊組件有幾種方式,一種是監(jiān)聽了動態(tài)鏈接時 image 二進制文件加載完成的回調(diào),通過修改代碼段的方式判斷對應(yīng)的模塊進行注冊;第二種是在 +load 方法里面注冊;第三種是異步注冊,但是這種方式存在一個問題,可能組件使用方準備使用組件的時候,這個組件還未注冊成功。
BeeHive 還為組件設(shè)置了優(yōu)先級的概念,它通過數(shù)組來保持優(yōu)先級排序,在源碼中能看到一些數(shù)組排序的邏輯,這就帶來了相當多的高時間復(fù)雜度的運算。
所以,組件數(shù)量過多的話,會延長動態(tài)鏈接庫的過程。
BeeHive 為了讓每一個組件享有獨自的 app 生命周期、3D touch 等功能,會將這些系統(tǒng)級的事件發(fā)送給每一個組件,且不談大量的方法調(diào)用損耗,它必須讓入口文件 AppDelegate 繼承自 BeeHive 的 BHAppDelegate,筆者感覺侵入性過強,并且當開發(fā)者需要復(fù)寫 AppDelegate 方法的時候,還要注意讓super調(diào)用一下,可以說很不優(yōu)雅了。
在基于協(xié)議的組件化方案中,組件使用方能直接拿到目標組件的實例,那么使用者可能對該實例進行修改,這可能會帶來安全問題。
(3) 使用 Target-Action 解耦
Casa Taloyum 前輩的 iOS應(yīng)用架構(gòu)談 組件化方案 為此做出了好實踐。
Mediator 使用 Target-Action 來間接的調(diào)用目標組件,無需專門注冊。組件維護者需要做一個 Mediator 的分類,通過硬編碼調(diào)用目標組件,然后組件使用者只需要依賴這個分類就行了。封裝的 Mediator 源碼只有簡單的 200+ 行代碼,并且很易懂。這也讓開發(fā)者能對組件化的實施更加有信心,不會因為基礎(chǔ)設(shè)施的錯誤而束手無策。
小總結(jié)
關(guān)于以上組件化的簡單表述僅代表筆者的個人見解,由于筆者并沒有真正的實施組件化,所以理解可能有誤。
雖然筆者設(shè)計的 iOS 架構(gòu)不會應(yīng)用組件化,但是這給我們的架構(gòu)設(shè)計帶來了前瞻性的引導,這非常重要。
模塊化思維劃分文件;
在團隊開發(fā)中,項目發(fā)展到后期總是會出現(xiàn)某些文件或代碼難以管理,出現(xiàn)這種情況的主要原因通常是項目開發(fā)過程中對文件的管理過于隨意。
開發(fā)者應(yīng)該盡量將所有代碼文件歸于模塊,而不要出現(xiàn)模擬兩可的文件。而筆者這里說的模塊,是有具體意義的模塊,比如圖片處理模塊、字體處理模塊,而不是諸如 Public、Common 等無具體意義的代碼文件。
試想,在多人開發(fā)中,當所有人都覺得有些代碼不知道怎么歸類的時候,就會往 Public 里面扔。當你某天想要整理一下這個 Public,會發(fā)現(xiàn)已經(jīng)無從下手;或者當你需要遷移項目中的某個業(yè)務(wù)模塊時,會附帶遷移一些模塊,當這個模塊是有意義的(比如圖片處理模塊),你的遷移成本會非常低,但是當這個藕斷絲連的模塊是 Public 時,時間成本可能高于你的想象,估計你會將它完整的拷貝過去,而又對新項目造成了污染。
全局的公共文件是產(chǎn)生垃圾代碼的源頭。筆者認為幾乎所有的代碼都是可以歸類為模塊的。
大致梳理了一個文件分類,當然這個分類是靈活的,只是要分模塊劃分:
- GeneralModules 放項目獨有的通用配置模塊(比如通用顏色模塊、通用字體模塊)
- ToolModules 放工具類模塊(比如系統(tǒng)信息模塊)
- PackageModules 放基于業(yè)務(wù)的一些封裝(比如提示框模塊、加載菊花模塊)
- BusinessModules 放業(yè)務(wù)模塊(比如購物車、個人中心)
具體里面放了些什么,可以查看筆者的 DEMO。
減少全局宏的使用;
很多時候,過多的宏讓項目很不整潔,每一個開發(fā)者都往全局文件添加宏,而往往只是一段簡單的代碼,筆者認為開發(fā)中應(yīng)該盡量少使用宏,原因如下:
宏在預(yù)編譯階段替換為實際代碼,存在效率問題
使用宏的地方可能只需要一塊內(nèi)存,但是宏替換過后開辟了多個(這種情況應(yīng)該用常量替換宏)
可能存在潛在的宏命名沖突
宏包裝過多的代碼難以理解和調(diào)試
代碼遷移時需要處理全局的宏
實際上,非得使用宏的地方并非那么多,比如需要定義一個全局的導航欄字體方便使用,可以將通用字體的配置參數(shù)作為一個模塊:
@interface HQGeneralFont : NSObject
/** 導航欄標題字體 */
+ (UIFont *)navigationBarTitleFont;
@end
或者用常量來代替宏:
.h
FOUNDATION_EXTERN NSString * const kNotify_xxx;
//xxx通知 key.m
NSString * const kNotify_xxx = @"kNotify_xxx";
這么做也便于轉(zhuǎn)換思維,畢竟 swift 中是沒有宏的。

去基類化設(shè)計;
代碼設(shè)計中,應(yīng)該盡量避免基類的使用,也就是說,你不應(yīng)該總是要求開發(fā)者去繼承你的基類來做功能。使用基類將造成不可避免的耦合,為業(yè)務(wù)的長期發(fā)展帶來阻礙(當然某些情況是可以使用基類的)。
其實使用基類就算了,若是將大量的業(yè)務(wù)邏輯放入基類中將是災(zāi)難的開端。試想,當項目新成員一來就看見成千上萬行的基類代碼TA作何感想?
另外一種場景,當需要將項目中的某個模塊遷移到其他項目,或者需要將其他項目合并入當前項目,基類的合并將是一個非常頭疼的問題,它藕斷絲連的模塊和代碼會讓你抓狂。
那么,類的工具方法應(yīng)該放哪兒?對所有類的統(tǒng)一配置應(yīng)該放哪兒?對封裝模塊的個性化定制應(yīng)該怎么做?
裝飾模式
類的工具方法,按道理說可以提取為模塊,但是有些場景可能顯得不夠簡潔。
其實只要留意 iOS 官方的 API,你就不難發(fā)現(xiàn)裝飾模式的大量應(yīng)用,使用數(shù)個分類將大量的方法按照功能分類,會清晰且優(yōu)雅:
@interface UIViewController (HQGeneral)
/** 基礎(chǔ)配置 */
- (void)HQGeneral_baseConfig;
@end
@interface UIViewController (HQGeneralBackItem)
/** 配置通用系統(tǒng)導航欄返回按鈕 */
- (void)HQGeneral_configBackItem;
/** 重寫該方法以自定義系統(tǒng)導航欄返回按鈕點擊事件 */
- (void)HQGeneral_clickBackItem:(UIBarButtonItem *)item;
@end
不過要注意的時,定義分類的時候一定要加一個前綴標識以避免方法覆蓋。
AOP
面向切面編程在 iOS 領(lǐng)域經(jīng)典的應(yīng)用就是利用 Runtime 去 Hook 方法:
+ (void)load {
[self HQGeneralHook_exchangeImplementationsWithOriginSel:@selector(viewDidLoad) customSel:@selector(HQGeneralHook_viewDidLoad)];
}
+ (void)HQGeneralHook_exchangeImplementationsWithOriginSel:(SEL)originSel customSel:(SEL)customSel {
Method origin = class_getInstanceMethod(self, originSel);
Method custom = class_getInstanceMethod(self, customSel);
if (origin && custom) {
method_exchangeImplementations(origin, custom);
}
}
- (void)HQGeneralHook_viewDidLoad {
NSLog(@"進入:%@", self);
[self HQGeneral_baseConfig];
if (self.navigationController && [self.navigationController.viewControllers indexOfObject:self] != 0) {
[self HQGeneral_configBackItem];
}
[self HQGeneralHook_viewDidLoad];
}
代碼中統(tǒng)一配置了 UIViewController 的系統(tǒng)導航欄返回按鈕,注意這里調(diào)用的業(yè)務(wù)配置方法都是定義在 UIViewController 的分類里面的。若有某些導航欄需要格外配置返回按鈕的需求,可以拓展一個屬性來控制。
面向協(xié)議設(shè)計模式
對于一些封裝的組件,多考慮使用協(xié)議來個性化定制,繼承作為最差方案,而非是選方案。
定義一個遵守組件定制協(xié)議的屬性是常用的解決方法:
@property (nonatomic, strong) id strategy;
不同的屬性作為不同的策略,組件內(nèi)部通過調(diào)用對應(yīng)的協(xié)議方法實現(xiàn)個性化定制。而當使用者想要改變策略時,只需要更改這個屬性就行了。面向協(xié)議設(shè)計模式結(jié)合策略模式是一個很好的實踐。
MVC?MVP?MVVM?VIPER?;
業(yè)務(wù)具體的架構(gòu)模式是個讓很多開發(fā)者頭疼的問題,因為有時候能讓復(fù)雜業(yè)務(wù)更清晰,有時候卻因為膠水代碼過多而臃腫。
實際上為什么要嚴格的遵守架構(gòu)模式呢?為什么每一個業(yè)務(wù)模塊的架構(gòu)模式都要一模一樣呢?
筆者認為正確的架構(gòu)思路一定是根據(jù)業(yè)務(wù)來的,不同的模塊,不同的業(yè)務(wù)線完全可以有不同的架構(gòu),只需要架構(gòu)足夠清晰不至于晦澀。
大致設(shè)計了一下架構(gòu)的主旋律:
DataCenter 負責數(shù)據(jù)的獲取、處理、緩存等。
Model 設(shè)計為“瘦” Model,便于復(fù)用和遷移;也考慮到數(shù)據(jù)源可能數(shù)量龐大,若 Model 設(shè)計得過于“胖”,會造成更多的內(nèi)存占用。
View 負責數(shù)據(jù)的展示,可以根據(jù)業(yè)務(wù)情況權(quán)衡是否需要 ViewModel 處理界面邏輯。
ViewController 作為 DataCenter 和 View 的橋梁。
筆者設(shè)計的項目目前不會很復(fù)雜,多數(shù)情況上面的架構(gòu)就已經(jīng)夠用,若某個頁面功能過多,完全可以提取一些額外的模塊,比如 DataCenter 處理過于復(fù)雜,那就把數(shù)據(jù)的處理和緩存提取出來:xxxDataProcesser、xxxDataCache。這些都是靈活的,只需要按照模塊化的思維提取,ViewController 的代碼相信也不會太多。
關(guān)于響應(yīng)式框架
Reactivecocoa 雖然強大,筆者以前也用過,不過它是一個重量級框架,學習成本有點高,可能會因為團隊成員對其了解不足導致難以定位的錯誤。
而美團的 EasyReact 似乎是一個福音,筆者大概瀏覽了一下源碼,質(zhì)量確實很高,對性能方面的處理很精致,基于圖論算法的處理也感覺很棒,項目侵入性也很小。不過缺點就是太新了,需要開發(fā)社區(qū)一定時間的驗證,暫時筆者持觀望態(tài)度。

本文標題:iOS 響應(yīng)式架構(gòu)設(shè)計方案
鏈接URL:http://jinyejixie.com/news/131239.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供域名注冊做網(wǎng)站、用戶體驗、網(wǎng)站建設(shè)商城網(wǎng)站、自適應(yīng)網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

微信小程序開發(fā)
和政县| 莱阳市| 休宁县| 陈巴尔虎旗| 格尔木市| 汝州市| 合江县| 梅州市| 汨罗市| 霍山县| 潞城市| 南川市| 余姚市| 乃东县| 舞阳县| 阿拉尔市| 合水县| 崇阳县| 白银市| 巨野县| 广汉市| 个旧市| 隆德县| 荃湾区| 博客| 射阳县| 罗源县| 荣成市| 汝南县| 新邵县| 新密市| 佳木斯市| 长泰县| 临西县| 旬邑县| 恩施市| 同江市| 温宿县| 婺源县| 互助| 巨野县|