开发杂谈iOSios专题

iOS组件化实践(三):实施

2017-01-27  本文已影响2893人  CodeWeaver

前言

上一篇中我们对组件化的准备工作做了介绍,这篇文章我们以SXNews为例进行组件化,Demo地址在这里,壳工程获取脚本在这里,希望本文能给你带来帮助。

一、修改配置

根据上一篇文章所述,你应该已经有了ModularizationDemo文件夹,此时该文件夹中只有configOldProject两个子文件夹。这时我们应该针对项目情况,修改config内容。

这里是SXNewsPodfile

SXNews的Podfile

根据这个文件,我们可以得知该项目主要使用了RAC等框架开发,因此为了方便起见,我们需要修改一下我们的config:

cd ~/ModularizationDemo/config

添加私有源

cp config.sh config_category.sh
cp -r templates/ templates_category/

%s#templates#templates_category#g

pod 'ReactiveCocoa','2.5'  
pod 'HLNetworking', '~> 2.0.0.beta'  
pod 'MJExtension', '~> 2.0'  
pod 'SDWebImage','~> 3.7'

pod 'Lothar', '~> 1.0.5'

至此,配置文件已经修改完成,这里有我写好的配置文件,可以根据需求更改里面的参数。

二、创建组件模块

SXNews这个项目结构很简单,分为SearchDetailPhotoSetWeatherNewsReplyMain这7个业务组件和ToolsOther这两个公共文件夹。根据前两篇文章的内容,我们在这一节先将7个业务组件拆分出来。

先根据划分好的业务组件建立组件仓库:

HTTPS: https://github.com/ModularizationDemo/Search.git
SSH: git@github.com:ModularizationDemo/Search.git
HomePage: https://github.com/ModularizationDemo/Search

cd ~/ModularizationDemo/config  
./config.sh
建立本地组件仓库 完成后的文件夹目录 拆分好之后的项目目录

三、去除组件依赖

1. 提取公共代码

本系列文章的前两篇也说过,在项目开发中,难免会产生形如Common或者Tools这样的公共代码,在组件化中,应当将这些代码细分为各种二方库;在本例中,由于这一块代码量很少,因此直接将这部分所有代码生成一个私有pod,作为基础库供于其他组件使用。


SXAdManager修改前
SXAdManager修改后 编辑Tools.podspec文件
git add .  
git commit -m "Tools 1 init"  
git push  
git tag 1  
pod lib lint // 如果这一步通过了就上传tag
git push --tags  
pod repo push myspec --allow-warnings // myspec是上一篇文章中准备好的私有pod仓库的名字,--allow-warnings是忽略警告,pod提供了很多参数,具体请查阅cocoapods.org

如果一切正常,完成的结果在终端显示如下:

完成结果

这样我们的公共代码就提取好了。

2. 解除组件横向依赖

接下来我们以Search模块为例,介绍其解除于其他模块耦合的方法,限于篇幅,Lothar相关的方法就不写说明了,具体请查阅Lothar的项目介绍及注释

第一步 创建组件的服务接口

- (nullable UIViewController *)Search_aViewControllerWithKeyword:(nullable NSString *)keyword;

- (nullable UIViewController *)Search_aViewControllerWithKeyword:(nullable NSString *)keyword {
    NSMutableDictionary *dict = [NSMutableDictionary dictionary];
    if (keyword) {
        dict[kSearchKeyword] = keyword;
    }
    return [self performTarget:@"Search" action:@"aViewController" params:[dict copy] shouldCacheTarget:YES];
    }
}

#import <Search-Category/Lothar+Search.h>

UIViewController *viewController = [[Lothar shared] Search_aViewControllerWithKeyword:sender.titleLabel.text];
[self.navigationController pushViewController:viewController animated:YES];

第二步 实现组件服务

接着我们在Search模块中支持这个服务:

- (UIViewController *)Action_aViewController:(NSDictionary *)params;

- (UIViewController *)Action_aViewController:(NSDictionary *)params {
   NSString *keyword = params[@"keyword"];
   UIStoryboard *sb = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
   SXSearchPage *sp = [sb instantiateViewControllerWithIdentifier:@"SXSearchPage"];
   sp.keyword = keyword;
   return sp;
}
- (UIViewController *)Action_aViewController:(NSDictionary *)params {
    NSString *keyword = params[@"keyword"];
    UIStoryboard *sb = [UIStoryboard storyboardWithName:@"SXSearchPage" bundle:nil];
    SXSearchPage *sp = sb.instantiateInitialViewController;
    sp.keyword = keyword;
    return sp;
}
// Lothar+Detail.h
- (nullable UIViewController *)Detail_aViewControllerWithDocid:(nonnull NSString *)docid;

// Lothar+Detail.m
- (UIViewController *)Detail_aViewControllerWithDocid:(NSString *)docid {
    NSMutableDictionary *dict = [NSMutableDictionary dictionary];
    if (docid) {
        dict[@"docid"] = docid;
    }
    return [self performTarget:@"Detail" action:@"aViewController" params:[dict copy] shouldCacheTarget:YES];
}
UIViewController *viewController = [[Lothar shared] Detail_aViewControllerWithDocid:[self.searchListArray[indexPath.row] docid]];
[self.navigationController pushViewController:viewController animated:YES];

第三步 旧工程中实现组件服务

// Target_Detail.h
- (UIViewController *)Action_aViewController:(NSDictionary *)params;

// Target_Detail.m
- (UIViewController *)Action_aViewController:(NSDictionary *)params {
    SXNewsEntity *model = [[SXNewsEntity alloc]init];
    model.docid = params[@"docid"];
    
    UIStoryboard *sb = [UIStoryboard storyboardWithName:@"News" bundle:nil];
    SXDetailPage *devc = (SXDetailPage *)[sb instantiateViewControllerWithIdentifier:@"SXDetailPage"];
    devc.newsModel = model;
    return devc;
}
pod 'Tools', '1'

pod 'Search-Category', :path => '../Search-Category'
pod 'Search', :path => '../Search'
pod 'Detail-Category', :path => '../Detail-Category'

3.提交并上传仓库

提示:如果出现pod search找不到私有仓库的情况,可以先使用rm ~/Library/Caches/CocoaPods/search_index.json命令清除pods的索引再搜索。

当所有组件都拆分完毕并调试无误之后,就可以给组件打tag并提交版本了,这里我们还是以Search为例,具体方法如下:

看完这篇文章,你应该已经基本完成项目的组件化,下一篇将阐述如何优化组件化后的代码以及相应的一些规范。

参考文章

念纪-模块化与解耦

limboy-蘑菇街组件化之路

limboy-蘑菇街组件化之路-续

Casa Taloyum-iOS应用架构谈-组件化方案

Skyline75489-浅析iOS应用组件化设计

philon-iOS组件化思路-大神博客研读和思考

philon-iOS组件化实践方案-LDBusMediator练就

bang-iOS组件化方案探索

携程移动端架构演进与优化之路

iOS-组件化架构漫谈

上一篇下一篇

猜你喜欢

热点阅读