当我们新建一个 Cocoa 项目时,Xcode 会提供一系列的模板,我们选择Single View App即可。
可构建应用内购买内容包盒空工程——内置收费功能的应用。
输入必要的配置信息后,这些信息包括:
由于苹果的封闭性,对 Cocoa 项目的管理基本上都在 Xcode 中进行,Xcode提供了从文档、编码、调试、测试,再到签名、打包、上线的全流程支持。
随着开发的深入,我们的项目变得越来越复杂,各种链接库、子工程相互引用,不同 Target、Scheme 配置混杂,还会遇到多人协作开发时诡异的冲突。
Schema、Target、Project 和 Workspace 是组成一个 Xcode 工程最核心的单元,也是我们首先需要理解的部分。
Target 是我们工程中的最小可编译单元,每一个 target 对应一个编译输出,这个输出可以是一个链接库,一个可执行文件或者一个资源包。它定义了这个输出怎样被 build 的所有细节,具体包括:
在ios项目中, Build Settings,Build Phases 中配置的各种选项,大部分都是需要对应到指定的 target 的。
并且,每次我们在 Xcode 中 run/test/profile/analyze/archive 时,都必须指定一个 target。
工程中的 targets 有时候会共享很多代码、资源,这些相似的 targets 可能对应同一个应用的不同版本,比如 iPad 版和 iPhone 版,或者针对不同市场的版本。
Project 很好理解,Project就是一个 Xcode 工程,它管理工程下的所有targets 集合以及它们的源码,引用的资源,framework 等等。
Project 是管理资源的容器,本身是无法被编译的,所以每个 project 至少应该有一个可编译的 target,否则就是一个空壳。一个 target 编译时引用的资源是它所在 project 所有管理资源的子集。
我们也可以对 project 进行配置,包括基本信息和编译选项(Build Settings)等,这些配置会应用到它管理的所有 targets 中,但是如果 target 有自己的配置,则会覆盖 project 中对应的配置。
在很多情况下,我们的工程中只有一个 project。可以在 finder 中双击后缀名为.xcodeproj 的文件,就可以直接打开单个 project 了。
如果我们需要从源码编译一个依赖库,可以把这些源码所在的工程作为主工程的subProject 添加到目录结构中去。
当一个 target 被多个不同的项目依赖,或者 project 之间互相引用,那么我们就需要把这些 projects 放到相同的层级上来。管理相同层级 projects 的容器就是 Workspace。
和 projects,target 不同,workspace 是纯粹的容器,不参与任何编译链接过程,它主要管理:
在 iOS 开发中,我们常常使用 Cocoapods 来管理三方库,它会把这些三方库的源码组装成一个 project,和主工程一起放入到 workspace 中,自动配置好主工程与 pods 库之间的依赖。所以如果引入了 Cocoapods,我们必须打开这个新的 workspace 才能正常 build 原来的项目。
我们知道苹果手机中的每个APP都有一个沙盒,APP就是一个信息孤岛,相互是不可以进行通信的。但是iOS的APP可以注册自己的URL Scheme,URL Scheme是为方便app之间互相调用而设计的。我们可以通过系统的OpenURL来打开该app,并可以传递一些参数。
URL Scheme必须能唯一标识一个APP,如果你设置的URL Scheme与别的APP的URL Scheme冲突时,你的APP不一定会被启动起来。scheme的命名应该是只能纯英文字符,而不能含有下划线或者数字。
日常开发中我们常常点击 Xcode 左上角的 Run 箭头来运行调试代码,这其实就是执行了 Scheme 定义的一个任务。
针对一个指定的 target,scheme 定义了 build 这个 target 时使用的配置选项,执行的任务,环境参数等等。Scheme 可以理解为一个工作流,或者蓝图,当我们点击 debug,test 按钮时,Xcode 会按照 scheme 中的定义,去执行对应的工作流。
Scheme 中预设了六个主要的工作流: Build, Run, Test, Profile, Analyze, Archive。包括了我们对某个 target 的所有操作,每一个工作流都可以单独配置。
Scheme 中最重要的一个配置是选择 target 的 build configuration,对每一个 project,会有两个默认的 build configuration:debug 和 release。
每个 configuration 对应了 build target 时不同的参数集,比如宏,编译器选项,bundle name 等等。我们可以在 target 的配置页中更改这些选择项,也可以自己创建新的 build configuration,比如为 App 创建免费和付费版本的配置。
除了 build configuration 外,scheme 还可以配置:
注:以下部分截取自网络。
在ios开发中,你简单最糟心的项目是什么,肯定有人会说要多糟心有多糟心,曾经我也见到过很糟心的项目,没有采用任何框架,编译都好几分钟的那种。 下面是一个传统的MVC方式开发的项目的分包:
由于,此种分别,很多代码都写在一块,于是又出现了按照功能进行的分包策略。例如:
可以看到,项目就是按照功能进行分包,然后进行业务迭代,估计也是很多公司的项目的样本。而我们队项目进行了一些简单的归类,归类的示意图如下:
这样一来,我们的工程主要有三大部分:Core、Resource、SupportingFiles。其中,Core存放我们的代码,也是文章主要说明的部分。Resource用于存放资源,例如图片、音效、文件等等,SupporrtingFiles用于存放pch、main.m等等文件。
Core的分组主要分为AppDelegate、Modules、NetWork/Requests、Services、General、Macro、Vendors等六个大模块。
AppDelegate文件只存放AppDelegate的h和m文件,也可以放入其他跟AppDelegate有关的文件,比如我们写了一个AppDelegate+Router的Category文件,用来处理rootViewController的变化,这个也应该放到这个分组来比较清晰,而不是放到General的Category。
Modules用于存放应用的业务逻辑代码,总而言之,Modules就是放App主要业务逻辑和功能代码的地方。
服务模块,主要提供应用的基础服务,比如说Apns推送管理,数据库,本地推送等等,这一类的封装之后的功能模块。
所有的第三方类库都放到Vendors里面。
此种分别只供参考,并不绝对和权威,实际采用的分包和开发方案还得根据实际情况,或者配合一些诸如MVVM等框架来进行拆包。