写在前面
应同事邀请, 在简书分享一些开发方面的经验. 所以有了这篇文章.
这不是一篇Objective-C/Swift的学习教程. 我想给那些学完开发语言、了解了一些API阶段的同学们 分享一些开始构建一个App工程时的一些内容.
让我们开始吧.
创建工程
Xcode "Create a new Xcode project"
根据你要建立的应用的需求不同, 当然可选不同的模板来初始化工程.
但绝大多数时间, 我推荐你从“Single View App
”开始你的项目;
因为其他模板里的功能, 都可以在以后添加进项目, 而一般情况下, 现在的应用有很多必须的东西这些模板里都没有, 例如Splashscreen之后大部分应用都有几页全屏大图的介绍页; 或者很多应用都有的主界面是个tab控制器掌控着多个navigation控制器.
好吧, 坦白说, 其实我们想要的应该是个空的项目有一些基础的配置文件. 大概来说从“Single View App”来开启这个项目更接近我们想要的状态.
作为项目的代码肯定是会被VCS(版本控制系统)托管的, 那么创建完初始化工程之后再把它整个丢进仓库吧~ 这里就不用同时创建本地git仓库.
这里我会以单一视图模板来创建一个TestApp工程.
组织工程
组织方式当然就各有不同了.
有的公司有相关规范, 那很好, 遵守它来创建, 你的项目在公司将会更容易被后来人维护;
网络上也有很多人分享他们组织归纳文件的方式, 也可以参考学习;
或者你自己的归纳方法.
这里稍微说一下我常用的:
-
AppDelegate
保留在原始位置, 项目根目录; - 项目根目录下的归类的文件夹我都习惯以一个下划线开头, 这个习惯要从很久以前的 Finder 排序文件规则并不会优先排列文件夹开始说起, 加了下划线以后, 文件夹出聚集出现在前面;
- 要展示的每一个界面都归到
_Scene
目录下; - 常量归到
_Constant
目录下; - 模块归到
_Module
目录下; - 图片、音频、字体等资源归到
_Resource
目录下; - Xcode 的 Project Navigator(⌘1) 里的文件夹, 应该和磁盘上的文件夹一一对应; 因为如果Xcode都用虚拟文件夹, 文件一多起来, 它们可能都被凌乱的丢在工程根目录 or 任何地方, 找起来是一大麻烦.
如果照上边一番整理, 我们的初始工程可能会看起来比较像这样:
不管你使用哪种方式去组织工程, 遵守它就好.
视窗
这里要说的是关于视图构建的事儿.
Xcode 现在默认都是以 Storyboard 形式创建工程.
Storyboard 有很多优势, 但是我觉得协同工作时, 不是很方便.
大部分时候, 一个项目里会有很多很多的视图/视图控制器, Storyboard会比较大, 打开的速度问题, 在机械硬盘的电脑上尤为明显. (当然希望各公司都给配SSD的Mac)
再就是多人同时编辑一个Storyboard时, 处理VCS里的合并问题; 合并真的太多啦, 毕竟应用开发有很多构建视图的工作.
所以我推荐使用独立的 nib 文件来做视图, 也就是常见的 .xib
文件.
这样一来, 它可以像Storyboard一样方便的使用 AutoLayout 超好用的布局设计工具, 又方便团队开发; 而且因为分散界面, 每个文件也很小, 方便读取.
就是少了 Storyboard 里的视图控制器与视图控制器的关联配置, 不过这部分用代码来操作也很方便; 有时候还很必要, 因为我们经常需要在某些代码判断条件下决定视图跳往哪个视图, 有时候我们会在跳转前, 设置一些新视图的属性值等情况.
这样一来, 应用到当前的TestApp工程上:
- 在工程的 Targets配置里, 删除填写在
Deployment Info
>Main Interface
里的数据(比如是Main), 让它置空. 因为我们不准备再用这个Storyboard文件了. - 从工程里删除对应的Storyboard文件(比如是Main.storyboard)
- 编辑AppDelegate; 未从Storyboard初始化视窗, 我们需要在代码里手动初始化.
编辑 AppDelegate.m 文件的-application:didFinishLaunchingWithOptions:
方法:
// 初始化Window
_window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
// 配置根视图控制器
_window.rootViewController = 某某试图控制器实例;
// 让window显示出来
[_window makeKeyAndVisible];
依赖管理
基本的工程清理好了, 现在该给它增加依赖管理了.
现在iOS应用常用的依赖管理是 Cocoapods 和 Carthage , 以后还可以用上官方的 Swift Package Manager.
这里呢, 就拿Cocoapods介绍一下.
你当然得安装好Cocoapods; 如果还没, 可以用macOS的一款包管理器Homebrew 来安装它, 命令:
brew install cocoapods
如果连Homebrew也没有, 也可以用一行命令先安装它:
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
brew很方便, 现在用来安装Cocoapods, 或是以后想装个Go-lang啊, 或是Vim啊, 又或是carthage、mtr... 那些你想要用的工具, 都可以用它方便的安装与管理.
这里你已经能好好用pod了.
那么命令行进到项目跟目录下:
# 生成Podfile
pod init
# 根据Podfile生成工作空间
pod install
因为还没加任何pod, 所以应该很快会跑完.
正常跑完这个install命令会提示类似如下内容:
[!] Please close any current Xcode sessions and use `TestApp.xcworkspace` for this project from now on.
Sending stats
Pod installation complete! There are 0 dependencies from the Podfile and 0 total pods installed.
那从今往后就该使用 *.xcworkspace
文件来打开工程了.
Pod的使用网上有许多参考内容, 这里就不多说. 附上官方网站: Cocoapods.
版本控制
前面说, 项目中的代码肯定是有代码版本控制系统管理在的, 所以我们不在那时又去创建本地git仓库.
现在要将工程代码放到仓库里, 我们就要指定好哪些文件被版本控制系统来管理.
例如这里我们用git系统, 可以在工程根目录放置一个.gitignore
文件, 来指明被git系统忽略的文件/文件类型.
推荐一个 git ignore 文件的模板网站: gitignore.io
比如在这选上 Objective-C 和 Swift 语言, 选上 macOS 系统:
就可以生成一份它们推荐的这些语言/这些系统下被忽略的文件/文件类型. 可以创建一个空白的.gitignore
文件把它们复制粘贴进去.
然后做一点想要的修改.
因为我们在用Cocoapods, 那么稍微思考一下:
- 这里传入仓库的工程, 其他人克隆出的运行的环境如何? 是内外离线环境吗? 如果不能方便的使用
pod install
, 那我们则应该将Pods目录也放到仓库(也包括生成的.xcworkspace
); 这样克隆后, 依赖库都已经存在, 无需pod install即可直接运行工程; - 存在对各个库版本的指定要求吗? 如果是这样, 我们比较应该上传Podfile.lock文件. 这是在操作
pod install
时, 由pod
计算出满足条件依赖设置的情况下, 要下载使用的, 最新版本的各个库 的信息; 也就是说, 这里详细记录着当前你运行的项目里, 使用那些依赖库的版本; 将它加入版本控制, 这样其他人克隆并使用该工程时,pod install
会直接读取这个.lock
文件指定的版本信息, 保持使用库的版本一致. 这种情况, 可以将Pods
以下所有文件忽略. - 还有其他情况? 要不要忽略
Podfile.lock
文件呢? 这是没有特定答案的. 你需要考虑的是, 忽略/添加的后果是什么. 前面说了添加它可以用来确保协作时使用同一版本; 那忽略它, 意味着每一次(无Podfile.lock)文件下的pod install
, 都会挑选满足条件下的最新版本库. 这样的话, 如果某些库的API变更导致你的使用也需要调整时, 你得及时修复. 另外, 如果你用CI, 遇到这种情况CI是不会帮你修复的. (同理, CI上一定是要跑pod install
而不是pod update
).
这里我们选择记录 Podfile, Podfile.lock, 忽略 Pods.
贴出来瞧瞧:
# Created by https://www.gitignore.io/api/macos,swift,objective-c
### macOS ###
*.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
### Objective-C ###
# 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
*.dSYM.zip
*.dSYM
# CocoaPods - Refactored to standalone file
Pods/*
# Carthage - Refactored to standalone file
# 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://docs.fastlane.tools/best-practices/source-control/#source-control
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots
fastlane/test_output
# Code Injection
#
# After new code Injection tools there's a generated folder /iOSInjectionProject
# https://github.com/johnno1962/injectionforxcode
iOSInjectionProject/
### Objective-C Patch ###
### Swift ###
# Xcode
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
## Build generated
## Various settings
## Other
## Obj-C/Swift specific
## Playgrounds
timeline.xctimeline
playground.xcworkspace
# Swift Package Manager
#
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
# Packages/
# Package.pins
.build/
# CocoaPods - Refactored to standalone file
# Carthage - Refactored to standalone file
# 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://docs.fastlane.tools/best-practices/source-control/#source-control
# End of https://www.gitignore.io/api/macos,swift,objective-c
小结
到这里, 初始化工程的任务就完成啦!~
我们回顾一下:
- 创建了工程;
- 定义/组织好工程目录结构;
- 挑选了工程视图构建方式;
- 配置了依赖管理系统;
- 配置了版本控制系统.
作者
骆昱(Luo Yu), 2018-05-09
本作品采用知识共享署名 3.0 中国大陆许可协议进行许可。