总结一些iOS项目中组织代码的方法 clean code

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
查看查看254 回复回复1 收藏收藏 分享淘帖 转播转播 分享分享 微信
查看: 254|回复: 1
收起左侧

总结一些iOS项目中组织代码的方法 clean code

[复制链接]
苏格拉没有底 发表于 2016-7-7 09:57:03 | 显示全部楼层 |阅读模式
快来登录
获取优质的苹果资讯内容
收藏热门的iOS等技术干货
拷贝下载Swift Demo源代码
订阅梳理好了的知识点专辑
0、前言

总结一些组织代码的方法,大到各个子项目模块之间,小到单个文件内部,涉及到了CocoaPods私有库、Carthage构建私有Framework、项目内Group和文件夹、类内用Category组织、文件内的#pragam mark、// MARK -。虽然有些老生常谈,就当是重新梳理一遍吧=。=。

总结一些iOS项目中组织代码的方法 1

总结一些iOS项目中组织代码的方法 clean code - 敏捷大拇指 - 总结一些iOS项目中组织代码的方法 1





1、多个子项目 - CocoaPods加私有仓库

感觉目前CocoaPods已经成了搞iOS开发的标配了,基本上所有的第三方库和组件都可以通过CocoaPods来集成管理。但是CocoaPods的功能其实不止管理第三方库和组件,团队内部的拆分出来的子项目和子模块,同样可以用CocoaPods来集成管理。

先看看如下Podfile的示例:

[Swift] 纯文本查看 复制代码
# 源配置 #
source 'git@gitlab.xxx.com:cocoapods/specs.git' # 团队内部Gitlab源
source 'https://git.coding.net/xxx/specs.git' # Coding等私有Git托管平台

# iOS版本支持 #
platform :ios, '7.0'

# 开发中的子项目 #
pod 'XXXCommonUI', :path=> '/Users/tutuge/projects/Xcode/XXXCommonUI' # 本地路径

# 依赖的内部子项目 #
pod 'XXXModuleA', :git=> 'git@gitlab.xxx.com:cocoapods/XXXModuleA', :branch=>'develop'
pod 'XXXModuleB', '1.0.1'

# 依赖的开源第三方库 #
pod 'AFNetworking','3.0.0'
pod 'DTCoreText'

# 额外的脚本 #
# ...




1.1、私有Git仓库

虽然我们有万能的Github了,但是还是有些代码是不能公开的=。=,所以需要一个私有的Git仓库。

有自己服务器的,完全可以用Gitlab(或者Gogs)搭建一个功能强大的私有Git仓库,管理项目代码,搭建CocoaPods私有源都很不错。

当然,懒得折腾的,也可以用第三方的私有Git服务,如:BitbucketCoding等。



1.2、私有CocoaPods源

搭建一个私有CocoaPods源其实就是创建一个私有的Spec Repo,说白了就是一个存放了所有私有Pods的Podspec文件的,按照特定结构组织的目录,然后把这个目录推到私有Git仓库就成了一个私有的CocoaPods源。

Spec Repo的目录结构示例如下:

[Swift] 纯文本查看 复制代码
├── Specs
    └── [XXXModuleA]
        └── [0.0.1]
            └── [XXXModuleA].podspec.json
        └── [0.0.2]
            └── [XXXModuleA].podspec.json


然后添加私有源即可:

[Shell] 纯文本查看 复制代码
pod repo add XXXSpecRepo [url=https://git.coding.net/xxx/specs.git]https://git.coding.net/xxx/specs.git[/url]




1.3、创建私有CocoaPods项目的具体步骤

至于具体的创建步骤,CocoaPods的官方文档和一些优秀的博客已经说得很清楚了,我就不再重复了。推荐阅读:CocoaPods Guides,还有使用Cocoapods创建私有podspec,这篇很详细!



1.4、引用正在本地开发的子项目

主工程依赖的子项目也是可以同时开发的,用path指定路径即可,如

[Shell] 纯文本查看 复制代码
pod 'XXXCommonUI', :path=> '/Users/tutuge/projects/Xcode/XXXCommonUI'


,然后pod install一下,依赖的本地工程就会集成到主工程的Development Pods目录下,开发时,就可以同时修改主项目和子项目了。




2、构建私有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非常不错~



2.1、创建Framework

这里的Framework指的是Cocoa Touch Framework动态框架,静态Framework的缺点不少(如不能共享已加载到内存的二进制目标代码、构建麻烦等),如果项目可以从iOS 8开始支持,为啥不用动态框架呢~

创建Framework的过程非常简单,Xcode 6以后就有了Framework项目模板,直接选中“Cocoa Touch Framework”模板,按照提示来即可。记得在 TARGETS -> Build Phases -> Headers -> Public 加入要暴露的头文件(Swift的话,将要暴露的类、方法标记public)就好。



2.2、用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,就可以集成测试。



2.3、最终的Cartfile

由于Carthage的去中心化,用Carthage管理项目的Framework依赖就非常灵活,一个简单的示例如下:

[Shell] 纯文本查看 复制代码
# 开发中的本地Framework
git "file:///directory/to/project" "develop"

# 依赖的私有Framework
git "git@gitlab.xxx.com:cocoapods/XXXFramework.git" "development"

# 第三方开源库
github "Mantle/Mantle" ~> 1.0


所以,Carthage可以方便的管理构建本地、私有、第三方的Framework库,而且更加方便~

详细的创建流程Google一下就有很多,如Build your own Cocoa Touch Frameworks, in pure SwiftCreating your first iOS FrameworkHow to Make a Carthage-compatible Framework in Swift



2.4、和CocoaPods混用

Carthage是没有任何侵入性的,不会对项目工程有修改,只是构建出了Framework文件,所以完全可以把Carthage当做纯粹的Framework构建工具,跟CocoaPods一起愉快的使用=。=




3、项目内文件组织 - Group和文件夹

项目内的代码组织,其实就是代码文件的组织,总的来说,其实有以下三种:

  • 具有物理文件夹结构的Folder reference
  • 从Xcode创建的逻辑上的Group
  • 具有物理文件夹结构的Group




3.1、排除Folder reference

Folder reference说白了就是硬盘上一个文件夹的逻辑引用,有点像Linux文件系统里面的软连接=。=,图标是蓝色的,将一个文件夹拖到Xcode中时,Create folder references选项创建的就是。

虽然编译时也会被打包到程序中,更能同步真正文件夹内部的修改,但是遗憾是的里面的代码文件是不能自动的加入到Xcode的编译中的,要手动一个一个加,而且图片资源也不能在IB里面使用,代码里面使用也要加上路径,所以一般是纯资源文件夹用Folder reference的方式引用,对于组织代码文件,就可以排除Folder reference的方式。



3.2、纯逻辑Group文件平铺,脱离Xcode不方便查看

首先要明确的是,Group是Xcode对文件的一种逻辑上的引用,并且在编译时Xcode会把所有的Group展开,所以代码里面也就不用像Folder reference一样加上路径,还可以针对Target作区分,很方便。

但是Xcode中创建的Group并没有对应到文件系统中的文件夹,导致一旦脱离Xcode看代码,所有的文件都平铺在了根目录下,非常不方便。

难道没有办法了?



3.3、有物理文件夹结构的Group最好

还有一种Group是可以有物理文件夹结构的,其实将一个文件夹拖到Xcode中,选择Create groups for any added folders创建的Group就是既有Group的有点,又可以保持物理文件夹结构。这样无意是最好的~


3.3.1、手动创建:

可以Add Files To XXXX,然后选择New Folder创建文件夹,然后把代码文件拖进去,再添加回Xcode。


3.3.2、自动创建:

对于现有的大量的Group,手动一个一个创建实在不方便,还好有个命令行工具:synx,直接在工程根目录运行synx XXX.xcodeproj就可以自动为Group创建物理文件夹。


当然,CocoaPods管理的库要重新pod install一次,手动添加的Framework也要重新添加。


总结一些iOS项目中组织代码的方法 2

总结一些iOS项目中组织代码的方法 clean code - 敏捷大拇指 - 总结一些iOS项目中组织代码的方法 2





4、类内代码组织 - Category

Objective-C中的Category实在是太方便了,可以灵活的为现有的类增加方法,甚至是系统的类。

但是其实Category也可以拿来组织一个类的实现,将类的Property、方法按照业务、功能拆分到不同的Category里面,使类的结构更加清晰。

系统API本身就有大量的例子,如UIViewController的:

[Swift] 纯文本查看 复制代码
@interface UIViewController (UIContainerViewControllerCallbacks)
// ...
@end

@interface UIViewController(UIViewControllerTransitioning)
// ...
@end


实现的时候还可以每个Category对应一个头文件和.m文件,类的结构更加清晰:

[Swift] 纯文本查看 复制代码
XXXClass.h
XXXClass.m
XXXClass+XXXModuleA.h
XXXClass+XXXModuleA.m
XXXClass+XXXModuleB.h
XXXClass+XXXModuleB.m





5、文件内代码组织 - #pragam mark、// MARK -

整理文件内的代码时,最好的手段就是用#pragam mark宏定义,Swift的话就是// MARK -

Objective-C冗长的语法注定了一个代码文件的行数不会少=。=,如果没有一定的规范,实在是难以迭代,所以最好就是开发前约定一种规则,对主要的类的实现都约定出一套规范,如UIViewController的子类、UIView的子类、UITableViewCell的子类等,然后开发人员按照这个规范写代码,这样才能使代码更好维护。

如,UIViewController的子类实现时,可以按照如下顺序组织代码:

[Swift] 纯文本查看 复制代码
@implementation XXXViewController

// 内存相关
#pragma mark - Memory manager

- (instancetype)init
- (void)dealloc

// 类生命周期相关的
#pragma mark - Life cycle

(void)viewDidLoad

// 类的Public方法
#pragma mark - Public methods

// 所有的Actions
#pragma mark - Actions

- (void)didTapCancelButton:(UIButton *button)

// 通知回调,具体可以细分
#pragma mark - Notifications - XXX

// 系统的Delegate
#pragma mark - UITableViewDelegate

// 自定义类的Delegate
#pragma mark - XXXDelegate

// 自定义View、初始化等
#pragma mark - Custom views

// 类私有方法
#pragma mark - Private methods

@end


当然,具体的组织方法还要根据项目本身的架构、模式决定,上面的只是参考。



5.1、进一步:创建项目专属文件模板

既然定下了文件内的组织顺序,每次写代码手工输入也还是有点麻烦,所以更进一步的话就是创建自定义的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 7Creating Custom Xcode Templates敏捷大拇指上的各位Swift开发者可自行阅读~




6、最后

一切为了更加干净整洁的代码,“May the clean code be with you”





7、参考

CocoaPods
Carthage
Xcode Groups vs. Folder References
Framework vs Library (Static & Shared) in (Cocoa/OSX, Cocoa Touch/iOS)
onevcat-如何打造一个让人愉快的框架




8、相关内容

Swift GYB 简易教程,一个 Swift 内部使用的模板生成源文件工具

iOS Xcode制作模板类

总结一些iOS项目中组织代码的方法 clean code

Swift实战-模板模式




作者:土土哥

都看到这里了,就把这篇资料推荐给您的好朋友吧,让他们也感受一下。

回帖是一种美德,也是对楼主发帖的尊重和支持。

*声明:敏捷大拇指是全球最大的Swift开发者社区、苹果粉丝家园、智能移动门户,所载内容仅限于传递更多最新信息,并不意味赞同其观点或证实其描述;内容仅供参考,并非绝对正确的建议。本站不对上述信息的真实性、合法性、完整性做出保证;转载请注明来源并加上本站链接,敏捷大拇指将保留所有法律权益。如有疑问或建议,邮件至marketing@swifthumb.com

*联系:微信公众平台:“swifthumb” / 腾讯微博:@swifthumb / 新浪微博:@swifthumb / 官方QQ一群:343549891(满) / 官方QQ二群:245285613 ,需要报上用户名才会被同意进群,请先注册敏捷大拇指

嗯,不错!期待更多好内容,支持一把:
支持敏捷大拇指,用支付宝支付10.24元 支持敏捷大拇指,用微信支付10.24元

评分

参与人数 1金钱 +10 贡献 +10 专家分 +10 收起 理由
Anewczs + 10 + 10 + 10 32个赞!专家给力!

查看全部评分

创客 发表于 2016-7-11 18:42:51 | 显示全部楼层
记住这一条规则就行:千万别重复。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

做任务,领红包。
我要发帖

分享扩散

都看到这里了,就把这资料推荐给您的好朋友吧,让他们也感受一下。
您的每一位朋友访问此永久链接后,您都将获得相应的金钱积分奖励
关闭

站长推荐 上一条 /3 下一条

热门推荐

合作伙伴

Swift小苹果

  • 北京治世天下科技有限公司
  • ©2014-2016 敏捷大拇指
  • 京ICP备14029482号
  • Powered by Discuz! X3.1 Licensed
  • swifthumb Wechat Code
  •   
快速回复 返回顶部 返回列表