Swift 模块化项目结构最佳实践

原文链接:http://liuduo.me/2017/05/22/moduleproject/
微博:@刘铎Derek

这篇文章没有技术,只讲怎么用 Xcode 组织项目结构。

开篇

写了这么多年的代码,目前觉得最好的构造项目结构的方式就是 模块化

模块化在 Objective-C 的项目中可能比较难搞起来,但是在 Swift 项目中就游润有余了,因为 Swift 有着天生 Module 的概念,和它的访问控制修饰符。

小型项目搞模块化意义可能不大,对于中型和大型的项目,模块化以后,纵向分层横向分模块,模块间解耦,访问控制,依赖注入,依赖倒转,在开发过程中就能自然而然的写出来,省去以后重构的苦恼。

大家都知道,Xcode 主要是用 WorkspaceProject 来组织项目结构的,一个工程只能有一个 Workspace,一个 Workspace 中可以有任意多个 Project

而模块化的方式就是把各个业务功能拆分成模块(Framework),然后主工程负责把这些业务模块串联起来构成一个完成的 App。

工程结构

在一个项目里,有一个 Workspace,其中有很多个 Project,主工程是一个 Project,每个业务模块也都是一个 Project

效果是这样的:

在工程中,每添加一个新模块的时候,通过点击左下角的 + 来创建,选择 Framework 类型:

路径选择到 Modules 目录下。

如果你觉得需要的话,可以对 Modules 目录下的这些 Project 再分目录。

如何创建 Workspace?

如果是从一个新工程开始创建,可以在 Xcode 中选择:File -> New -> Workspace... 创建,然后再在创建好的 Workspace 中添加主工程。

如果你是用了 CocoaPods,在第一次 pod install 时,CocoaPods 会帮你创建好 Workspace。

依赖配置

对于每一个模块 xcodeproj,都需要在这里严格配置好它的依赖。

同属于一个 WorkspaceProject 们,可以方便的互相配置依赖,Xcode 可以很好的处理好这个依赖。

配置了依赖以后的 Framework,在编译时 Xcode 会先编译它依赖的那些 Framework, 确保这个 Framework 可以顺利配置成功。

用这种项目结构时,依赖必须严格配置正确,否则即使在模拟器或真机运行时没有问题,打包的时候一定会出现问题。这样当想知道一个模块依赖了哪些模块时,可以直观的从这里查看到。

为每一个模块添加 Demo 和单元测试

由于一个模块是一个单独的 Project,可以在里面方便的添加 Demo 和单元测试的 Target。

点坐下的 + 即可添加。

CocoaPods

如果你的某一个模块需要依赖 CocoaPods 中的库,CocoaPods 本身也很好的支持了这个需求。

Podfile 文件中添加一个 target 的配置即可。

target 'Slide' do
    project "Modules/Slide/Slide"
    pod 'SDWebImage', '3.8.2'
    pod 'SDWebImage/WebP'
end

Carthage

使用 Swift 语言的项目也会经常用到 Carthage。一般都是直接依赖 Carthage/Build 中编译好的 .framework 文件,然后类型为 App 的 Project,要配置 copy-framework 脚本,类型为 Framework 的 Project,要在 Build Phases 中添加一个 Copy Files Phases,这是官方文档中的说法。

但是在我们这种项目结构中,如果为每个模块都配置 Copy Files Phases,会导致打出来的包中,每个模块的 Framework 都包含了它依赖的那些 Framework,导致包大小非常大,因为里面包含了非常多的重复 Framework。

于是我们再 Workspace 中又建立的一个目录叫 CarthageFrameworks,然后把 Carthage/Checkout 目录中的那些 .xcodeproj 文件拖到这个 CarthageFrameworks 目录中,效果如下:

这样不仅解决了打包重复包含 Framework 的问题,还能方便的查看 Carthage 引入的库的代码,并且方便的设断点调试。

列举一下好处

  • 模块化,各模块之间独立,职责清晰
  • 开发过程中会自然强制你考虑模块间解耦,访问控制,依赖注入,依赖倒转等问题
  • 依赖必须严格配置,方便查看和梳理依赖
  • 每个 Project 都有一个 xxx.xcodeproj文件,这个文件是最常出现冲突的文件了,而且这个文件的冲突还往往很难解决,模块化分开后,各个模块都有单独的 xxx.xcodeproj 文件,大大降低发生冲突的概率。
  • 模块拥有自己的 Targets 空间,方便创建 Demo 和单元测试
  • 如果想把模块做成单独的 git 仓库,也非常的方便
  • 方便进行 Carthage 引入的库的调试
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容