1. 程式人生 > >iOS元件化開發

iOS元件化開發

一 . 為什麼要元件化?
對於一些小的專案,有一個或者兩三個人可以獨立完成的專案,沒有必要用元件化開發。元件化開發主要是為了解決專案越來越大,開發人員越來越多,專案耦合性高,不利於維護的問題。

二 . 什麼是元件化?
1.元件:一般來說用於命名比較小的功能塊,如:下拉重新整理元件、提示框元件。而較大粒度的業務功能,我們習慣稱之為”模組”。
2.元件化:也可稱為模組化,用來分隔,組織和打包軟體,每個特定的模組完成特定的功能,所有的模組按照特定的需求組織在一起,完成某些功能,形成一個整體。這就是元件化。
3.元件化首先思考的是模組的拆分,一般可以拆分成基礎模組和業務模組,基礎模組主要是提供一些基礎服務,底層實現,可能很多業務模組都要依賴基礎模組。例如網路請求模組。

三 . 元件化有什麼優缺點?
1.優點:解除耦合性,便於團隊合作開發,模組可以單獨執行,測試,加快編譯速度(較少主工程裡的編譯檔案),業務分層、解耦,使程式碼變得可以維護,便於各業務功能拆分、抽離,實現真正的功能複用。通過url跳轉,可以動態的控制頁面跳轉,可以統一處理頁面出問題之後的錯誤處理,可以統一三端,iOS,Android,H5。
2.缺點:增加了很多重複程式碼,元件維護問題,對於版本更新迭代快,多個版本同時開發的可能還會有元件之間不同版本的依賴問題。
總之,元件化開發有優點,也有缺點,但是總的來說優點還是大於缺點的。開發中可以根據情況來確定是否需要元件化開發。
四 . 怎麼實現元件化?
1.工程要分成幾個模組,哪些是基礎模組,哪些是業務模組,業務模組可能比較大,此時有要把大的業務模組分成幾個小的業務模組。具體怎麼分要考慮實際情況。
2.模組劃分完成以後,各個模組之間的通訊怎麼實現,比較常用的中介軟體,通過中介軟體實現模組之間的通訊。中介軟體是聯絡各個模組之間的通訊。中介軟體主要做的,就是處理元件之間的頁面跳轉和元件之間方法的呼叫。
中介軟體的目的之一是,解除元件之間的耦合性,讓各個模組獨立起來。
3.從實際開發來說,元件之間最大的需求就是頁面跳轉,需要從元件A的pageA頁面跳轉到元件B的pageB頁面,避免對元件B頁面ViewController標頭檔案的直接依賴。
4.元件化完成以後,就是管理組建,最常用的就是通過cocoapods管理。

五 . 元件化的原則
1.元件被定義為兩種型別的元件:基礎元件,業務元件。(我們還有第三方元件,屬於基礎元件)
2.基礎元件可以被業務元件依賴,基礎元件不可依賴業務元件。
3.業務元件之間不可耦合。
4.元件相互之間不能通過硬編碼引用的方式進行呼叫。通訊通過中介軟體實現。

六 . 元件化的過程中需要注意的問題?
1.當元件比較多的時候,它們的依賴關係、版本等的管理問題也就多了,元件管理起來可比較麻煩,可能需要制定一個元件管理機制,所以就需要整合管理。
七 . 常用的元件化方式有哪些?
1.MGJRouter
蘑菇街所採用的是 URL -> block的形式,通過URL和 block的鍵值對進行註冊。

[MGJRouter registerURLPattern:@"mgj://detail?id=:id" toHandler:^(NSDictionary *routerParameters) {
    NSNumber *id = routerParameters[@"id"];
    // create view controller with id
    // push view controller
}];

[MGJRouter openURL:@"mgj://detail?id=404”]

通過呼叫openURL來進行跳轉。
蘑菇街的URL有專門的後臺管理。這樣 就解決了被呼叫者檔案的引入問題,從而達到解耦。
但是他們 有 傳參的問題。
從url上可以看出來,他們只能傳基本引數,像物件之類的引數就無能為力。
2.CTMediator
CTMediator 是基於Target-Action模式。

-(void)addTarget:(id)target action:(SEL) forControlEvents:(UIControlEvents)controlEvents

CTMediator的做法是, 一個target對應一個mediator的category, 每個category裡的方法對應了這個target下所有可能的呼叫場景。
下面是以news為target,所建立的category

#import "CTMediator+NewsActions.h"
NSString * const kCTMediatorTarget_News = @"News";
NSString * const kCTMediatorActionNativTo_NewsViewController = @"NativeToNewsViewController";
@implementation CTMediator (NewsActions)
- (UIViewController *)yt_mediator_newsViewControllerWithParams:(NSDictionary *)dict {
    UIViewController *viewController = [self performTarget:kCTMediatorTarget_News
                                                    action:kCTMediatorActionNativTo_NewsViewController
                                                    params:dict];
    if ([viewController isKindOfClass:[UIViewController class]]) {
        return viewController;
    } else {
        NSLog(@"%@", NSStringFromSelector(_cmd));
        return [[UIViewController alloc] init];
    }
}
@end

通過mediator呼叫上面的category方法進行跳轉到news頁面

- (void)bButtonClick:(UIButton *)sender {    
    UIViewController *viewController = [[CTMediator sharedInstance] yt_mediator_newsViewControllerWithParams:@{@"newsID":@"123456"}];
    [self.navigationController pushViewController:viewController animated:YES];
}

相比 MGJRouter ,CTMediator使用category就可以很好的解決傳參的問題。
CTMediator是元件內會提供對外開放的需要被元件外需要的類名和屬性。

#import "Target_News.h"
#import "NewsViewController.h"
@implementation Target_News
- (UIViewController *)Action_NativeToNewsViewController:(NSDictionary *)params {
    NewsViewController *newsVC = [[NewsViewController alloc] init];
    if ([params valueForKey:@"newsID"]) {
        newsVC.newsID = params[@"newsID"];
    }
    return newsVC;
}
@end

3.LDBusMediator
LDBusMediator是利用URL->ViewController的形式。本地維護一個url與viewController的map,通過快速遍歷利用url生成viewController。

[LDBusMediator routeURL:[NSURL URLWithString:@"productScheme://ADetail"] withParameters:@{@"image":@""}

從url上可以看出,LDBusMediator方案是根據scheme和host用來匹配對應的viewcontroller,然後進行跳轉。
LDBusMediator傳參上可以在url上後接上引數,也可以通過字典的形式傳參。

八 . 從元件間呼叫方法的角度, 就是我們所說的中介軟體的服務。

1.MGJRouter
蘑菇街元件間的呼叫通過protocol來實現

[ModuleManager registerClass:ClassA forProtocol:ProtocolA]
[ModuleManager classForProtocol:ProtocolA]

蘑菇街通過ModuleManager這個類加了一個對映關係protocol->class
通過協議名拿到class,不過呼叫方不需要知道class的具體類名,因為協議的方法都在元件內實現,所以直接拿來用就行了。

2.CTMediator
CTMediator 元件間的呼叫就是通過上面講到的category 包含了target下所有場景下呼叫場景。
categary中開放的 方法供呼叫者呼叫。

[[CTMediator sharedInstance] CTMediator_showAlertWithMessage:@"casa" cancelAction:nil confirmAction:^(NSDictionary *info) {
            // 做你想做的事
            NSLog(@"%@", info);
        }];

3.LDBusMediator
LDBusMediator也是利用protocol來實現服務的呼叫。
LDBusMediator方案中,每個業務元件的實現自定義一個掛接點Connector_A,掛接點遵循中介軟體規定的connector協議;在掛接點需要連線上可導航的url,協議的服務承載例項。通過掛接點+協議的方式,元件的實現部分不用對外披露任何標頭檔案,從而達到解耦的目的。

通過connector向BusMediator掛接可處理的Protocol,根據Protocol獲取當前元件中可處理protocol的服務例項。

具體服務協議的實現可放到其他類實現檔案中,只需要在當前connetor中引用,返回一個服務例項即可

[[LDBusMediator serviceForProtocol:@protocol(ModuleAXXXServicePrt)] moduleA_showAlertWithMessage:@"casa" cancelAction:nil confirmAction:^(NSDictionary *info) {
            NSLog(@"%@", info);
        }];