iOS 工程规范
iOS 工程规范,之前为公司定了一个内部的 iOS 工程规范,其实也是我个人的风格,下面记录一下发出来。
Xcode 工程结构
注意事项
工程命名应该和项目一致,遵循 UpperCamelCase 写法(第一个词的首字母,以及后面每个词的首字母都大写,除了 iOS 的 i 这种),禁用中文。 为了避免文件杂乱,物理文件应该保持和 Xcode 项目文件同步。Xcode 创建的任何组(group)都必须在文件系统有相应的映射。 工程文件里不能记录某些账号和密码。 尽量不要有warning: 类似数据类型隐式转换这种低级的 warning 绝不能出现。类似 perform unrecognizer selector 这种 warning 可以用 #pragma clang diagnostic push 这种编译指令将其去掉(所有 warning 参见 fuckingclangwarnings.com)。对于 CocoaPods 安装第三方库带来的 warning 可以在 Podfile 中配置 inhibit_all_warnings! 去掉。对于开发者自己打的 warning ,在发布版本之前要逐个检查,确认无误或者完成后才能发布。 工程必须要有 README.md 和 CHANGELOG.md ,建议每个代码文件夹写一个 README.md 说明该模块是做什么的,起到文档作用。 工程中每个自己新建的文件都必须带有前缀标识,前缀标识必须全局一致,全部字母大写。
vc-架构">App 工程结构(目前仅适用于 Objective-C 工程,传统的 MVC 架构)
App 工程结构(目前仅适用于 Objective-C 工程,传统的 MVC 架构)
两种建议(假设下面的工程以 DMP 为前缀):
第一种是先按代码逻辑划分,再在每个目录中按功能模块细分:
|—— DemoProject | |—— Common: 存放全局通用的头文件,例如 DMPConstants.h, DMPAppKeys.h, DMPMacros.h | |—— Vendor: 不适合通过 CocoaPods 引入的第三方类库,例如需要经常改动的或者自己定制的 | |—— Resources: 存放各种资源,例如语言国际化文件组成的 bundle 文件,Images.xcassets 等 | |—— Utils: 工具类,可以便捷地迁移到其它工程 | | |—— Categories: 存放各种 Category | | |—— Helpers: 例如获取设备信息、App 信息之类的工具类 | |—— Models: 数据模型类 | |—— Logic: 各种业务逻辑类 | | |—— Global: 例如 App Config,Notification Center 这种全局通用的 | | |—— SDKWrapper: 为了避免 AppDelegate.m 过于庞大,可以把一些 SDK 逻辑封装下单独出一个类 | | |—— Network: 网络逻辑 | | |—— Storage: 数据持久化 | | |—— Cache: 缓存 | | |—— 其它根据工程自行拓展 | |—— Views: 视图类 | | |—— Common: 所有全局共用的 UI 组件 | | |—— TableView: | | | |—— Headers: UITableView 的 Headers | | | |—— Cells: UITableViewCell 子类 | | | |—— Footers: UITableView 的 Footers | | |—— CollectionView: | | | |—— ReusableViews: UICollectionReusableView 子类 | | | |—— Cells: UICollectionViewCell 子类 | | |—— Storyboards: 存放一个或多个 storyboard 文件 | | |—— Others: 针对特定场景定制的 UI 组件,根据功能划分模块,例如 Login, Home, My | |—— Controllers: 视图控制器类 | | |—— Base: 各种 ViewController 的根类,例如 DMPBaseViewController, DMPBaseTableViewController | | |—— Entrance: 存放各种 App 启动时的入口页面控制器,例如配置入口的 DMPControllersManager, 闪屏 DMPSplashController, 引导页 DMPIntroduceController, 正常入口 DMPRootTabBarController 等 | | |—— 根据功能划分模块,例如 Login, Home, My | |—— AppDelegate.h/m | |—— Supporting Files | | |—— Info.plist, main.m, pch 等 |—— DemoProjectUnitTests: 单元测试对应的目录 |—— Scripts: 在 Archive 时自动保存 dSYM 文件的脚本,读取 dSYM 和 Crash 的脚本等,不用添加到 Xcode 工程中 | |—— dSYM: 存放每次 Archive 生成的 dSYM
第二种是先按功能模块划分,再按代码逻辑划分:
假设有 Entrance, Home, Games, My 几个功能模块,分别表示程序入口,主页,游戏页面,个人主页。
|—— DemoProject | |—— Vendor: 不适合通过 CocoaPods 引入的第三方类库,例如需要经常改动的或者自己定制的 | |—— Resources: 存放各种资源,例如语言国际化文件组成的 bundle 文件,Images.xcassets 等 | |—— Base: 基础模块,为具体功能模块做支撑 | | |—— Common: 存放全局通用的头文件,例如 DMPConstants.h, DMPAppKeys.h, DMPMacros.h | | |—— Models: 数据模型类 | | |—— Views: 全局通用的视图类,自定的 UI 组件祖先类放在这里 | | |—— Controllers: 各种 ViewController 的根类,例如 DMPBaseViewController, DMPBaseTableViewController | | |—— Helpers: 便于迁移到其它工程的工具类 | | |—— Categories: 各种 Category | | |—— Logic: 负责各种基础逻辑的类 | | | |—— Global: 例如 App Config,Notification Center 这种全局通用的 | | | |—— SDKWrapper: 为了避免 AppDelegate.m 过于庞大,可以把一些 SDK 逻辑封装下单独出一个类 | | | |—— Network: 网络逻辑 | | | |—— Storage: 数据持久化 | | | |—— Cache: 缓存 | | | |—— 其它根据工程自行拓展 | |—— Modules: 各种功能模块 | | |—— Entrance: App 入口模块 | | | |—— Interfaces: 本模块公用的头文件,例如一些公用的常数、宏、Protocol、enum 定义等 | | | |—— Models: 本模块用到的数据模型类 | | | |—— Views: 本模块涉及的页面类 | | | |—— Controllers: 本模块涉及的视图控制器类 | | | |—— Helpers: 本模块涉及的业务逻辑类,例如负责布局的 LayoutUtil,负责动画的 AnimationUtil | | |—— Home: 主页模块 | | | |—— ... | | |—— Games: 游戏模块 | | | |—— ... | | |—— My: 个人主页模块 | | | |—— ... | |—— AppDelegate.h/m | |—— Supporting Files | | |—— Info.plist, main.m, pch 等 |—— DemoProjectUnitTests: 单元测试对应的目录 |—— Scripts: 在 Archive 时自动保存 dSYM 文件的脚本,读取 dSYM 和 Crash 的脚本等,不用添加到 Xcode 工程中 | |—— dSYM: 存放每次 Archive 生成的 dSYM
两种各有优缺点,可以自行根据喜好选择合适的结构。
在 Build Settings 中设置 Enable Modules 和 Link Frameworks Automatically 为 YES,避免手动引入各种系统 frameworks.
图片资源管理
图片资源管理
App 尽量使用 Images.xcassets 进行管理,必须包含 @2x 和 @3x 文件,较大的图片或背景图片可以使用 JPEG 格式代替。
图片文件命名采用
prefix_module_identifier_state 规则。
prefix 表示图片类型的前缀,举例:
icon btn bg line logo pic img
module 表示所属的场景模块,例如:common, home, my 等。
identifier 表示图片的标识。
state 表示素材的状态,例如按钮处于正常状态还是选中状态。
举例:icon_common_setting, btn_home_play_selected.
依赖管理
依赖管理
App 统一使用 CocoaPods 进行第三方依赖管理, SDK 尽量避免引入第三方类库。
Podfile 示例:
platform :ios, '7.0' # 指定 App 最低版本 # Target for App target "H5GameCenter" do pod 'AFNetworking', '~> 2.6.0' # 需要指定版本号 inhibit_all_warnings! # 禁止所有 warnings end # Target for Unit Tests target "HGCUnitTests" do pod 'OHHTTPStubs', '~> 4.3.0' inhibit_all_warnings! end
小提示:如果每次都用
pod install 命令安装,会非常慢,因为 CocoaPods 会检测类库是否需要更新,可以使用
pod install --no-repo-update 绕过检测更新进行安装。
代码管理
代码管理
1.分支管理统一用 git flow
2.Objective-C 工程 .gitignore 规范
# Xcode # # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore ## Build generated build/ DerivedData/ ## Various settings *.pbxuser !default.pbxuser *.mode1v3 !default.mode1v3 *.mode2v3 !default.mode2v3 *.perspectivev3 !default.perspectivev3 xcuserdata/ ## Other *.moved-aside *.xccheckout *.xcscmblueprint ## Obj-C/Swift specific *.hmap *.ipa # CocoaPods # # We recommend against adding the Pods directory to your .gitignore. However # you should judge for yourself, the pros and cons are mentioned at: # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control # # Pods/ # Carthage # # Add this line if you want to avoid checking in source code from Carthage dependencies. # Carthage/Checkouts Carthage/Build # fastlane # # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the # screenshots whenever they are needed. # For more information about the recommended setup visit: # https://github.com/fastlane/fastlane/blob/master/docs/Gitignore.md fastlane/report.xml fastlane/screenshots
3.commit message 不能太随意
测试
测试
对关键的逻辑必须要有单元测试。
Code Review
Code Review
暂无。