iOS組件化 方案 實現

iOS組件化

  • 組件化的原因
  • 現在流行的組件化方案
    • 方案一、url-block (基于 URL Router)
    • 方案二、protocol
      • 調用方式解讀
    • 方案三、target-action
      • 調用方式解讀
  • gitHub代碼鏈接參考

組件化的原因

  • 模塊間解耦
  • 模塊重用
  • 提高團隊協作開發效率
  • 單元測試

當項目App處于起步階段、各個需求模塊趨于成熟穩定的過程中,組件化也許并沒有那么迫切,甚至考慮組件化的架構可能會影響開發效率和需求迭代。而當項目迭代到一定時期之后,便會出現一些相對獨立的業務功能模塊,而團隊的規模也會隨著項目迭代逐漸增長,這便是中小型應用考慮組件化的時機了。

為了更好的分工協作,團隊會安排團隊成員各自維護一個相對獨立的業務組件。這個時候我們引入組件化方案,一是為了解除組件之間相互引用的代碼硬依賴,二是為了規范組件之間的通信接口; 讓各個組件對外都提供一個黑盒服務,而組件工程本身可以獨立開發測試,減少溝通和維護成本,提高效率。

進一步發展,當團隊涉及到轉型或者有了新的立項之后,一個團隊會開始維護多個項目App,而多個項目App的需求模塊往往存在一定的交叉,而這個時候組件化給我們的幫助會更大,我只需要將之前的多個業務組件模塊在新的主App中進行組裝即可快速迭代出下一個全新App。

現在流行的組件化方案

方案一、url-block (基于 URL Router)

通過在啟動時(load方法中)注冊組件提供的服務,把調用組件使用的url和組件提供的服務block對應起來,保存到內存中。在使用組件的服務時,通過url找到對應的block,然后通過block回調獲取服務。

url-block的架構圖如下:
在這里插入圖片描述

代碼說明

首先要在 + (void)load 中進行注冊

[LYXRouter registerURLPattern:@"lyx://foo/bar" toHandler:^(NSDictionary *routerParameters) {// create view controller// push view controllerstringWithFormat:@"routerParameters:%@", routerParameters]];}];

然后調用的時候傳入url:

    [MGJRouter openURL:@"lyx://foo/bar"];

代碼內部會通過傳入的url,拿到對應的block,然后進行調用。
之后block中的回調內部 就會執行 跳轉頁面的代碼了。

使用url-block的方案的確可以組建間的解耦,但是還是存在其它明顯的問題,比如:

  • 需要在內存中維護url-block的表,組件多了可能會有內存問題
  • url的參數傳遞受到限制,只能傳遞常規的字符串參數,無法傳遞非常規參數,如UIImage、NSData等類型
  • 沒有區分本地調用和遠程調用的情況,尤其是遠程調用,會因為url參數受限,導致一些功能受限
  • 組件本身依賴了中間件,且分散注冊使的耦合較多

方案二、protocol

是通過protocol定義服務接口,組件通過實現該接口來提供接口定義的服務,具體實現就是把protocolclass做一個映射,同時在內存中保存一張映射表,使用的時候,就通過protocol找到對應的class來獲取需要的服務。

protocol - class 架構圖如下:
請添加圖片描述

調用方式解讀

注冊:

[ModuleManager registerClass:ClassA forProtocol:ProtocolA]

調用:

[ModuleManager classForProtocol:ProtocolA]

具體流程可參考如下:
創建中間件
1、創建 組件化的中間件manager,中間件 提供注冊機制的方法,通過字典存儲 procotol-class
2、中間件manager 提供 通過協議獲取class的方法

- (void)registServiceProvide:(id)provide forProcotol:(Protocol *)procotol;- (id)serviceProvideForProcotol:(Protocol *)procotol;

業務側提供協議 + 遵循協議的類
1、提供協議,協議中提供 需要的方法

@protocol ProductDetailServiceProcotol <NSObject>
- (UIViewController *)productDetailViewControllerWithProductId:(NSString *)productId;@end

2、創建類,類遵循協議,實現協議方法,方法內部提供想要的 代碼
3、創建的類中的+ (void)load方法,內部 調用 中間件 注冊protocol-calss

@interface ProductDetailServiceProvide ()<ProductDetailServiceProcotol>@end@implementation ProductDetailServiceProvide//load 方法會在加載類的時候就被調用,也就是 ios 應用啟動的時候,就會加載所有的類,就會調用每個類的 + load 方法
+ (void)load
{[[ProcotolManager sharedManger] registServiceProvide:[[self alloc] init] forProcotol:@protocol(ProductDetailServiceProcotol)];
}#pragma mark - ProductDetailServiceProcotol- (UIViewController *)productDetailViewControllerWithProductId:(NSString *)productId
{ProcotolProductDetailViewController *detailVC = [[ProcotolProductDetailViewController alloc] init];detailVC.productId = productId;return detailVC;
}@end

調用
通過協議找到類,然后調用協議 方法「即:最終走的是 協議找到的那個class的方法」

id<ProductOrderServiceProcotol> servicePrivide = [[ProcotolManager sharedManger] serviceProvideForProcotol:@protocol(ProductOrderServiceProcotol)];UIViewController *orderVC = [servicePrivide productOrderWithProductId:self.productId];[self.navigationController pushViewController:orderVC animated:YES];

這種方案確實解決了方案一中無法傳遞非常規參數的問題,使得組件間的調用更為方便,但是它依然沒有解決組件依賴中間件的問題、內存中維護映射表的問題、組件的分散調用的問題。

方案三、target-action

重點詞: 分類 runtime
該方案 中間件是通過runtime來調用組件的服務,是真正意義上的解耦,也是該方案最核心的地方。具體實施過程是給組件封裝一層target對象來對外提供服務,不會對原來組件造成入侵;然后,通過實現中間件的category來提供服務給調用者,這樣使用者只需要依賴中間件,而組件則不需要依賴中間件。

調用方式解讀

創建中間件
中間件內部實現是通過runtime 拿到類和方法,進行調用的

@interface SYMediator : NSObject
+(instancetype)shareInstance;- (id)performTargetName:(NSString *)targetName actionName:(NSString *)actionName param:(NSDictionary *)dicParam;
@end

創建中間件的分類
分類中 的方法 調用 中間件的performTarget... 方法,來實現最終的方法調用。


#import "SYMediator+BookVC.h"static NSString *const kBookTarget = @"BookTarget";
static NSString *const kBookAction = @"bookVCWithParam";@implementation SYMediator (BookVC)
- (UIViewController *)bookViewControllerWithDicParam:(NSDictionary *)dicParm
{UIViewController *vc = [self performTargetName:kBookTarget actionName:kBookAction param:dicParm];if ([vc isKindOfClass:[UIViewController class]]) {return vc;} else {return [[UIViewController alloc] init];}
}
@end

創建target

組件封裝一層target對象來對外提供服務

@implementation BookTarget
- (UIViewController *)bookVCWithParam:(NSDictionary *)dicParm
{BookViewController *bookVC = [[BookViewController alloc] init];bookVC.bookName = dicParm[@"bookName"];bookVC.bookId = dicParm[@"bookid"];return bookVC;
}
@end

調用

NSDictionary *dicParm = @{@"bookName" : @"降龍十八掌",@"bookid" : @"sy0001"};//第一種方式(有category)UIViewController *bookVC = [[SYMediator shareInstance] bookViewControllerWithDicParam:dicParm];[self.navigationController pushViewController:bookVC animated:YES];

gitHub代碼鏈接參考

https://github.com/liyuunxiangGit/iOS-modularization

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/20114.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/20114.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/20114.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

網絡原理-四

一、續 當窗口大小為0,意味著緩沖區滿了,此時發送方,就因該暫停發送,發送方會周期性的除法 " 窗口探測包 " ,并不攜帶載荷,這樣的包對于業務不產生影響,只是為了觸發ACK,一旦查詢出來的結果是非0,緩沖區右有空間了,發送方就可以繼續發送. 二、擁塞控制 要限制發送方…

一步一步寫線程之十三隊列間的消息通知

一、線程和分布式的通信 隨著技術的不斷發展&#xff0c;多線程和分布式通信愈發的普及。那么在這種場景下的如何進行數據的通信&#xff0c;便成為了一個非常典型的問題。無論是多線程還是分布式&#xff0c;其實其抽象出來的通信機制都是類似的。或者說換句話&#xff0c;多…

java檢測字符串是否包含數字和字母

在Java中&#xff0c;要檢測一個字符串是否同時包含數字和字母&#xff0c;我們可以使用正則表達式&#xff08;regex&#xff09;或者通過遍歷字符串并檢查每個字符來實現。以下是兩種方法的詳細代碼示例&#xff1a; 1.方法一&#xff1a;使用正則表達式 import java.util.…

【AI+知識庫問答】沉浸式體驗了解 AI知識庫問答fastGPT

之前寫過一篇文章 【AI本地知識庫】個人整理的幾種常見本地知識庫技術方案 &#xff0c; 由于當時主要是針對AI本地知識庫&#xff0c; 所以沒列fastGPT。 最近經常刷到fastGPT&#xff0c;這里單獨水一篇。 FastGPT 是一個基于 LLM 大語言模型的知識庫問答系統&#xff0c;…

Github 2024-06-01 開源項目日報Top10

根據Github Trendings的統計,今日(2024-06-01統計)共有10個項目上榜。根據開發語言中項目的數量,匯總情況如下: 開發語言項目數量Python項目5Jupyter Notebook項目2TypeScript項目1Go項目1Shell項目1Lua項目1Kong:云原生API網關與AI能力 創建周期:3482 天開發語言:Lua協議…

如何確保績效目標執行到位?

很多企業在實施績效過程中&#xff0c;盡管制定好了績效目標&#xff0c;但是沒有執行下去&#xff0c;管理者將原因歸咎于“員工低效”、“體制機制”等問題&#xff0c;那么在人力資源管理方面&#xff0c;企業應該如何確保制定的績效目標執行到位&#xff1f;如何提高低效能…

云原生架構相關技術_4.服務網格

1.技術特點 服務網格&#xff08;ServiceMesh&#xff09;是分布式應用在微服務軟件架構之上發展起來的新技術&#xff0c;旨在將那些微服務間的連接、安全、流量控制和可觀測等通用功能下沉為平臺基礎設施&#xff0c;實現應用與平臺基礎設施的解耦。這個解耦意味著開發者無需…

React@16.x(14)context 舉例 - Form 表單

目錄 1&#xff0c;目標2&#xff0c;實現2.1&#xff0c;index.js2.2&#xff0c;context.js2.2&#xff0c;Form.Input2.3&#xff0c;Form.Button 3&#xff0c;使用 1&#xff0c;目標 上篇文章說到&#xff0c;context 上下文一般用于第3方組件庫&#xff0c;因為使用場景…

Chisel入門——在windows下vscode搭建|部署Scala2.13.3開發環境|用Chisel點亮FPGA小燈等實驗

文章目錄 前言一、vscode搭建scala開發環境1.1 安裝Scala官方插件1.2 創建hello_world.scala文件1.3 確認java的版本(博主使用的是1.8)1.4 下載Scala Windows版本的二進制文件1.5 配置環境變量1.6 交互模式測試一下1.7 vscode運行scala 二、windows安裝sbt2.1 下載sbt2.2 設置環…

函數遞歸及具體例子(持續更新)

遞歸就是函數自己調用自己 求n的階乘 n! n * (n - 1)! 直到n為1或者0的時候為止 舉個例子 int Fun(int n) {if (n < 0){return 1;}else{return n * Fun(n - 1);} }int main() {int n 0;scanf("%d", &n);int ret Fun(n);printf("%d\n", ret…

安裝Kubernetes v3 ----以docker的方式部署

以docker的方式部署 docker run -d \ --restartunless-stopped \ --namekuboard \ -p 80:80/tcp \ -p 10081:10081/tcp \ -e KUBOARD_ENDPOINT"http://192.168.136.55:80" \ -e KUBOARD_AGENT_SERVER_TCP_PORT"10081" \ -v /root/kuboard-data:/data \ e…

springboot中抽象類無法注入到ioc容器

1、背景 在寫代碼時&#xff0c;發現service接口有兩個實現類&#xff0c;并且兩個實現類中沒有對類名重命名&#xff0c;屬性注入的時候也沒有使用byName或Qualifier&#xff0c;正確情況下會發生多實現報錯的問題&#xff0c;以前對這個問題進行解析過。 2、調試過程 我想…

【設計模式】創建型-建造者模式

前言 在面向對象的軟件開發中&#xff0c;構建復雜對象時經常會遇到許多挑戰。一種常見的解決方案是使用設計模式&#xff0c;其中建造者模式是一個強大而靈活的選擇。本文將深入探討建造者模式的原理、結構、優點以及如何在實際項目中應用它。 一、復雜的對象 public class…

飛凌嵌入式FET3568/3568J-C核心板現已適配OpenHarmony4.1

近日&#xff0c;飛凌嵌入式為FET3568/3568J-C核心板適配了OpenHarmony4.1系統&#xff0c;新系統的加持使核心板在兼容性、穩定性與安全性等方面都得到進一步提升&#xff0c;不僅為FET3568/3568J-C核心板賦予了更強大的功能&#xff0c;也為開發者們提供了更加廣闊的創新空間…

每日一練編程題:今天是【接口,多態】

設計程序 : 電腦類的屬性USB接口數組 : 有3個usb插口電腦類的功能 : 通過接口插入外設 (u盤,麥克風,鍵盤等) addUSB(USB usb) { }開機 要求: 電腦開機前,先啟動外設關機 要求: 電腦關機前,先關閉外設 外設類(u盤,麥克風,鍵盤等) 功能 : 啟動 關閉 USB接口 定義usb設備的統一…

python多種方式 保留小數點位數(附Demo)

目錄 前言1. 字符串格式2. round函數3. Decimal模塊4. numpy庫5. Demo 前言 在Python中&#xff0c;保留小數點后特定位數可以通過多種方式實現 以下是幾種常見的方法&#xff0c;并附上相應的代碼示例&#xff1a; 使用字符串格式化&#xff08;String Formatting&#xff…

IDE集成開發環境

IDE集成開發環境&#xff0c;全稱“Integrated Development Environment” 介紹 定義&#xff1a; IDE是用于提供程序開發環境的應用程序&#xff0c;它集成了代碼編寫功能、分析功能、編譯功能、調試功能等一體化的開發軟件服務套。 組成部分&#xff1a; IDE通常包括代碼編…

Ubuntu20.04 Mysql基本操作知識

#Mysql基本知識 運行環境Ubuntu20.04 1.開啟mysql服務 sytemctl start mysql不然&#xff0c;命令行進入myql交互行提交命令后&#xff0c;就會出現4200錯誤。 2.顯示所有數據庫 SHOW DATABASES;注意復數s&#xff0c;畢竟很多數據庫 3.新建數據庫test CREATE DATABASE …

【學習筆記】計算機組成原理(九+十)

控制單元的功能 文章目錄 控制單元的功能9.1 微操作命令的分析9.1.1 取指周期9.1.2 間址周期9.1.3 執行周期9.1.4 中斷周期 9.2 控制單元的功能9.2.1 控制單元的外特性9.2.2 控制信號舉例9.2.3 多級時序系統9.2.4 控制方式 控制單元的設計10.1 組合邏輯設計10.1.1 組合邏輯控制…

LabVIEW與Simulink的通信及調用方式

LabVIEW和Simulink可以通過多種方式進行通信和集成&#xff0c;實現數據交互和功能調用。常見的通信方式包括TCP/IP、UDP、共享內存等&#xff0c;此外還可以利用MATLAB Script Node和S-Function等直接調用對方的功能。這些方法使得LabVIEW和Simulink能夠協同工作&#xff0c;充…