原文链接:
文章扼要:
- 多个子项目 - CocoaPods加私有仓库
- 构建私有Framework - Carthage
- 项目内文件组织 - Group和文件夹
- 类内代码组织 - Category
- 文件内代码组织 - #pragam mark、// MARK -
- 最后
前言
总结一些组织代码的方法,大到各个子项目模块之间,小到单个文件内部,涉及到了CocoaPods私有库、Carthage构建私有Framework、项目内Group和文件夹、类内用Category组织、文件内的#pragam mark、// MARK -。虽然有些老生常谈,就当是重新梳理一遍吧=。=。
多个子项目 - CocoaPods加私有仓库
感觉目前CocoaPods已经成了搞iOS开发的标配了,基本上所有的第三方库和组件都可以通过CocoaPods来集成管理。但是CocoaPods的功能其实不止管理第三方库和组件,团队内部的拆分出来的子项目和子模块,同样可以用CocoaPods来集成管理。
先看看如下Podfile的示例:
1 | # 源配置 # |
私有Git仓库
虽然我们有万能的Github了,但是还是有些代码是不能公开的=。=,所以需要一个私有的Git仓库。
有自己服务器的,完全可以用Gitlab(或者Gogs)搭建一个功能强大的私有Git仓库,管理项目代码,搭建CocoaPods私有源都很不错。
当然,懒得折腾的,也可以用第三方的私有Git服务,如:Bitbucket、Coding等。
私有CocoaPods源
搭建一个私有CocoaPods源其实就是创建一个私有的Spec Repo
,说白了就是一个存放了所有私有Pods的Podspec
文件的,按照特定结构组织的目录,然后把这个目录推到私有Git仓库就成了一个私有的CocoaPods源。
Spec Repo
的目录结构示例如下:
1 | ├── Specs |
然后添加私有源即可:
1 | pod repo add XXXSpecRepo https://git.coding.net/xxx/specs.git |
创建私有CocoaPods项目的具体步骤
至于具体的创建步骤,CocoaPods的官方文档和一些优秀的博客已经说得很清楚了,我就不再重复了。推荐阅读:CocoaPods Guides,还有使用Cocoapods创建私有podspec,这篇很详细!
引用正在本地开发的子项目
主工程依赖的子项目也是可以同时开发的,用path
指定路径即可,如pod 'XXXCommonUI', :path=> '/Users/tutuge/projects/Xcode/XXXCommonUI'
,然后pod install
一下,依赖的本地工程就会集成到主工程的Development Pods
目录下,开发时,就可以同时修改主项目和子项目了。
构建私有Framework - Carthage
除了抽离出子项目,用Framework的方式来管理公共代码也是不错的选择,Framework的好处也是多多的:
- 本质上是个bundle,不仅可以打包代码,还可以打包资源Assets、视图XIB等
- 可以有选择的开放头文件、接口,避免了用CocoaPods集成子项目时,所有代码全部暴露的问题,只暴露需要的,代码更加清晰。
- 从iOS 8开始支持的Cocoa Touch Framework可以支持动态Framework,能在主App和各种Extension之间共享一份二进制目标代码,加快应用加载速度,减小体积,加快编译速度等。
基于Cocoa Touch Framework动态框架的种种优点,“去中心化”的轻量级依赖包管理工具Carthage也越来越受欢迎。
总的来说,Carthage没有CocoaPods那样的Spec Repo
中心,不会对现有项目工程修改,只是完成了拉取代码、构建Framework的工作,非常的轻量级,所以用来构建团队内公用的Framework非常不错~
创建Framework
这里的Framework指的是Cocoa Touch Framework动态框架,静态Framework的缺点不少(如不能共享已加载到内存的二进制目标代码、构建麻烦等),如果项目可以从iOS 8开始支持,为啥不用动态框架呢~
创建Framework的过程非常简单,Xcode 6以后就有了Framework项目模板,直接选中”Cocoa Touch Framework”模板,按照提示来即可。记得在TARGETS->Build Phases->Headers->Public"
加入要暴露的头文件(Swift的话,将要暴露的类、方法标记public)就好。
用Carthage构建Framework
Carthage只支持构建标记为“Shared”的项目Target,所以创建好了Framework工程后,还要设置Scheme为“Shared”,可以在当前Scheme的Edit Scheme
里面设置,也可以在Xcode的菜单Product->Scheme->Manage Schemes
里面设置。
然后就可以将Framework工程推送到Git仓库中,可以是Github,也可以是私有Git仓库,如上一节提到的Coding、Bitbucket等,只要本机可以正常访问即可。记住打上版本号tag。
然后就可以在一个测试工程中创建一个Cartfile
文件,输入Framework的Git路径,按照官方文档设置一下”Run Script”,运行carthage update
生成对应的Framework,就可以集成测试。
最终的Cartfile
由于Carthage的去中心化,用Carthage管理项目的Framework依赖就非常灵活,一个简单的示例如下:
1 |
|
所以,Carthage可以方便的管理构建本地、私有、第三方的Framework库,而且更加方便~
详细的创建流程Google一下就有很多,如Build your own Cocoa Touch Frameworks, in pure Swift、Creating your first iOS Framework、How to Make a Carthage-compatible Framework in Swift。
和CocoaPods混用
Carthage是没有任何侵入性的,不会对项目工程有修改,只是构建出了Framework文件,所以完全可以把Carthage当做纯粹的Framework构建工具,跟CocoaPods一起愉快的使用=。=
项目内文件组织 - Group和文件夹
项目内的代码组织,其实就是代码文件的组织,总的来说,其实有以下三种:
- 具有物理文件夹结构的Folder reference
- 从Xcode创建的逻辑上的Group
- 具有物理文件夹结构的Group
排除Folder reference
Folder reference说白了就是硬盘上一个文件夹的逻辑引用,有点像Linux文件系统里面的软连接=。=,图标是蓝色的,将一个文件夹拖到Xcode中时,Create folder references
选项创建的就是。
虽然编译时也会被打包到程序中,更能同步真正文件夹内部的修改,但是遗憾是的里面的代码文件是不能自动的加入到Xcode的编译中的,要手动一个一个加,而且图片资源也不能在IB里面使用,代码里面使用也要加上路径,所以一般是纯资源文件夹用Folder reference的方式引用,对于组织代码文件,就可以排除Folder reference的方式。
纯逻辑Group文件平铺,脱离Xcode不方便查看
首先要明确的是,Group是Xcode对文件的一种逻辑上的引用,并且在编译时Xcode会把所有的Group展开,所以代码里面也就不用像Folder reference一样加上路径,还可以针对Target作区分,很方便。
但是Xcode中创建的Group并没有对应到文件系统中的文件夹,导致一旦脱离Xcode看代码,所有的文件都平铺在了根目录下,非常不方便。
难道没有办法了?
有物理文件夹结构的Group最好
还有一种Group是可以有物理文件夹结构的,其实将一个文件夹拖到Xcode中,选择Create groups for any added folders
创建的Group就是既有Group的有点,又可以保持物理文件夹结构。这样无意是最好的~
手动创建:
可以Add Files To XXXX
,然后选择New Folder
创建文件夹,然后把代码文件拖进去,再添加回Xcode。
自动创建:
对于现有的大量的Group,手动一个一个创建实在不方便,还好有个命令行工具:synx,直接在工程根目录运行synx XXX.xcodeproj
就可以自动为Group创建物理文件夹。
当然,CocoaPods管理的库要重新pod install
一次,手动添加的Framework也要重新添加。
类内代码组织 - Category
Objective-C中的Category实在是太方便了,可以灵活的为现有的类增加方法,甚至是系统的类。
但是其实Category也可以拿来组织一个类的实现,将类的Property、方法按照业务、功能拆分到不同的Category里面,使类的结构更加清晰。
系统API本身就有大量的例子,如UIViewController的:
1 | @interface UIViewController (UIContainerViewControllerCallbacks) |
实现的时候还可以每个Category对应一个头文件和.m文件,类的结构更加清晰:
1 | XXXClass.h |
文件内代码组织 - #pragam mark、// MARK -
整理文件内的代码时,最好的手段就是用#pragam mark
宏定义,Swift的话就是// MARK -
。
Objective-C冗长的语法注定了一个代码文件的行数不会少=。=,如果没有一定的规范,实在是难以迭代,所以最好就是开发前约定一种规则,对主要的类的实现都约定出一套规范,如UIViewController的子类、UIView的子类、UITableViewCell的子类等,然后开发人员按照这个规范写代码,这样才能使代码更好维护。
如,UIViewController的子类实现时,可以按照如下顺序组织代码:
1 | @implementation XXXViewController |
当然,具体的组织方法还要根据项目本身的架构、模式决定,上面的只是参考。
进一步:创建项目专属文件模板
既然定下了文件内的组织顺序,每次写代码手工输入也还是有点麻烦,所以更进一步的话就是创建自定义的Xcode文件模板,把不同类的#pragma mark
顺序规则直接写到模板里面,以后开发人员创建文件时直接用项目专属的模板就可以了~
具体的创建Xcode模板的步骤不在本文范畴=。=,不过倒是发现了一个Xcode插件,专门用来创建模板的:Stencil: A plugin for Xcode allowing you to easily create custom file templates,以及对应的文章:Introducing Stencil,还有一些教程:How to Create Custom Project Templates in Xcode 7,Creating Custom Xcode Templates,读者可自行阅读~
补充,还有:https://github.com/uxyheaven/XYXcodeTemplate
最后
一切为了更加干净整洁的代码,“May the clean code be with you”
参考
- CocoaPods
- Carthage
- Xcode Groups vs. Folder References
- Framework vs Library (Static & Shared) in (Cocoa/OSX, Cocoa Touch/iOS)
- onevcat-如何打造一个让人愉快的框架