知 识 点 / 超 人
目录
1.iOS工程结构解析
- 1.1 Workspace
- 1.2 Project
- 1.3 Target
- 1.4 Schema
- 1.5 Configuration & xcconfig
2.多环境配置
iOS工程结构解析
iOS工程一般由:Schema -> Target -> Project -> Workspace ,这四部分核心单元组成一个 完整Xcode 工程
Workspace
Workspace:工作空间,用于管理同一个工作空间的多个project的关联关系。workspace 是纯粹的容器,不参与任何编译链接过程。
例:以cocoapods为例,如果你原本的仅仅是一个project,那么cocoapods会创建一个Pods的project用于进行第三方库源码管理,然后创建一个workspace。workspace让Pods的project与主project产生关联关系,这样就可以在主project中使用Pods的project管理的资源(这里并不是直接使用Pods的资源,而是使用Pods打包生成的.a库)。因此主project如果使用cocoapods的库,就必须使用workspace打开进行编译,否则会因为找不到引用库而报错。
Project
Project:包含项目代码、资源文件的所有信息的资源管理容器。project本身是无法被编译的,所以每个 project 至少应该有一个可编译的 target,否则就是一个空壳。而 target 编译时能引用的资源只能是它所在的 project 所管理的资源。
例如:cocoapods中,虽然Pods与主project在同一个workspace中,但是主project管理的资源与Pods的project管理的资源是互相独立的。编译时Pods会将管理的源码库编译成一个libPods.a文件,并导入到主project中,让主project对libPods.a进行资源管理。因此才得以正常引用使用
project包含的内容:
1.源文件
1.1 project中自己编写的.h和.m文件
1.2project中导入的静态库和动态库
1.3导入的资源文件(如.db文件、json文本、xml、plist等)
1.4图片资源
1.5界面资源文件(xib、storyboard等)
2.project中使用group去组织文件目录结构信息。 在文件结构的导航中,采用group去组织文件(实际开发中,尽量使用实体文件夹)
3.project的编译级别配置文件如(debug, release)
4.target
5.运行环境scheme
Target
Target:对指定代码和资源文件的具体构建方式,target 是project中最小的可编译单元,每一个 target 对应一个编译输出,这个输出可以是一个App包、一个链接库、一个可执行文件或者一个资源包。它定义了这个输出是怎样被 build 的所有细节,具体包括:
- 1.General:可以在里面调整常用的target设置,例如标识、签名和部署选项。
- 2.Signing & Capabilities:签名和功能,对target编译输出结果的签名和添加Apple提供的 “app 服务”功能。如 CloudKit、Game Center 或 App 内购买项目。要使用某些 app 功能服务,您必须对 app 进行预置,通过 Xcode 的项目编辑器添加功能。
- 3.Resource Tags:用来浏览和编辑工程中全部的tag和相关资源。 内容和使用详情可以查看这篇文章
- 4.Info:编辑project或target的属性,包括信息列表值、支持的文档类型和本地化。一个target对应一个info.plist文件。如果有多个target就有多个。
- 5.Build Settings:编译设置,编译时会根据里面的设置信息进行编译。内容和使用详情可以查看这篇文章
- 6.Build Phases:构建阶段,编辑和重新排序生成系统执行的任务,例如运行脚本、复制文件或链接到框架。内容和使用详情可以查看这篇文章
- 7.Build Rules:用来指定不同文件类型分别应该如何被编译。内容和使用详情可以查看这篇文章
Build Settings,Build Phases中配置的各种选项,大部分都是需要对应到指定的 target 的。project和target中都有Build Settings,如果设置矛盾会应用谁的?
分为两种情况:
1. project有设置,而taget没有设置,以project为准
2. project有设置,target有设置,以target为准
优先级关系(由高到低):
手动配置Target Build Settings > Target中配置的xcconfig文件 > 手动配置Project Build Settings > Project中配置的xcconfig文件
Scheme
Scheme:对指定target的编译环境配置。
在苹果的生态里,每个App每次启动都是在全新的一个沙盒中,运行的App是一个信息完全独立的个体,App之间是不可以直接进行通信的。但是iOS中可以通过URL Scheme进行App之间的调用和传递信息。可以通过target中的info的URL Types添加 URL Scheme ,在程序中通过的OpenURL来打开注册的URL Scheme 对应的app,并可以传递一些参数。
URL Scheme必须能唯一标识一个APP,如果你设置的URL Scheme与别的APP的URL Scheme冲突时,你的APP不一定会被启动起来。URL Scheme的命名应该是只能纯英文字符,而不能含有下划线或者数字。
//iOS10以后打开URL Scheme的方式
UIApplication *application = [UIApplication sharedApplication];
[application openURL:[NSURL URLWithString:@"wx"] options:@{} completionHandler:nil];
日常开发中我们常常点击 Xcode 左上角的 Run 按钮运行代码,本质上就是编译该target时执行Scheme 定义的一个任务。
scheme 定义了 build 这个 target 时使用的配置选项,执行的任务,环境参数等等。Scheme 可以理解为一个编译构建的工作流,当我们点击时,Xcode 会按照 scheme 中的定义,去执行对应的构建过程。
Scheme 中预设了六个主要的构建过程: Build, Run, Test, Profile, Analyze, Archive。Scheme 中包括了我们对某个 target 的所有操作,每一个构建过程都可以单独配置。我们可以去编辑修改每个target的scheme,也可以在Manager Schemes中添加Scheme
每一个 project中,会有两个默认的 build configuration:debug 和 release。scheme中必须选择对应的configuration类型。一个configuration对应一个.xcconfig文件。可以在project的info中的Configuration中添加新的configuration,然后在Configuration中指定configuration使用哪一种xxconfig文件。
Build:只编译不运行,将对应target编译成对应的结果对象
Run:编译运行调试,执行完Build过程后,将编译结果转换为运行结果对象进行运行调试。
Analyze: 用于进行静态代码分析,可检测潜在的内存泄露(不对称 retain/release 导致的 Potential Leak)或野指针(Use of memory after it is freed)问题。编译时可选择 Build Configuration 为 Debug 沿用证书配置;
Profile: 将调起 Instruments 工具进行动态代码分析,例如 使用 Allocations/Leaks 动态跟踪分析内存泄露。编译时可选择 Build Configuration 为 Debug沿用证书配置;
Test: 用于运行测试,模拟器会启动并执行测试套件;
Archive: 可以Export as Xcode Archive,然后将 .archive 中的 .app 拖入 itunes 可 打包生成 ipa 包。
scheme 还可以配置:
运行时的环境变量(Environment Variables)
启动时设置给 UserDefaults 的参数(Arguments Passed on Launch)
App 执行时的系统语言、模拟的定位坐标、国家等环境参数
runtime,内存管理,日志,帧率检测等调试选项
Configuration & xcconfig
Configuration:是project对target的编译环境的配置。一般工程默认会创建Debug和Release两种编译环境的配置。我们可以在project的info里面增加或删除配置的编译环境,对于不同编译环境下的参数可以直接在target中的General、Signing & Capabilities、Resource Tags、Info、Build Settings、Build Phases、Build Rules设置。也可以通过xcconfig进行设置。
xcconfig:本质是一个键值对的纯文本文件,Configuration中选择对应的xcconfig文件后,编译时会根据xcconfig的内容进行相关的配置。xcconfig中可以自定义变量,也可以去修改系统的变量,从而修改工程编译的配置信息。xcconfig文件的语法比较简单,每个配置文件都由一系列键值分配组成,
key = value
例如:修改Build Settings 里的 Other Linker Flags
//OTHER_LDFLAGS 是 Build Settings 里的 Other Linker Flags的简称变量名
//在xcconfig中加入以下代码,用于修改修改Build Settings 里的 Other Linker Flags值
OTHER_LDFLAGS = $(inherited) -ObjC -l"HYJADCrash"
编译后,会发现Build Settings 里的 Other Linker Flags变为了
如果要查找OTHER_LDFLAGS这样的系统变量,可以在官网里查找。当然也可以直接在Build Settings里选择对应系统key使用'Command+C',然后'Command+V'复制到xcconfig,就能看见对应key的系统变量的简称了。
如果配置了xcconfig,那么就算修改了Build Settings的内容,最终编译也会根据xcconfig里的内容进行覆盖。基本上Build Settings中的内容,都可以在xcconfig中进行配置。
xcconfig补充:
注释:
xcconfig中只有 //
一种注释方式,如果要在xcconfig中定义一些网址,就不能直接用https://www.baidu.com。因为//会被认为是注释。为了避免这种情况,可以单独定义一个变量表示/。用变量代替//。就不会被编译器认为是注释了
Test_SLASH = /
//隐私政策地址
Test_PRIVACY_URL = https:${XKL_SLASH}${XKL_SLASH}www.baidu.com
include导入其他xcconfig
在创建xcconfig文件的时候,可以根据需求,创建多个。也就意味着,可以通过include关键字导入其他xcconfig内的配置。通过 include关键字后接上双引号:
#include "Debug.xcconfig"
在搜索引入的文件时,如果是以/开头,代表绝对路径,例如:
//表示确切的文件位置
#include "/Users/xieyujia/Desktop/heyujia的gitHub/HYJADCrash/Pods/Target Support Files /Pods-LoginApp/Pods-HYJADCrash.debug.xcconfig"
或者通过相对路径,以${SRCROOT}路径为开始:
#include "Pods/Target Support Files/Pods-LoginApp/Pods-LoginApp.debug.xcconfig"
变量
变量定义,按照0C命名规则,仅由大写字母,数字和下划线(__)组,原则上尽量大写。字符串可以是-也可以是'号。 变量有三种特殊情况:
在xcconfig中定义的变量与Build Settings的一致,那么会发生覆盖。可以通过$(inherited),让当前变量继承变量原有值。例 如:
OTHER_LDFLAGS = -framework SDWebImage
OTHER_LDFLAGS = $(inherited) -framework AFNetworking
// OTHER_LDFLAGS = -framework SDWebImage -framework AFNetworking
注意:有部分变量不能通过xcconfig配置到Build Settings中,例如:配置PRODUCT_BUNDLE_IDENTIFIER不起作用。
引用变量,$()
和${}
两种写法都可以:
TEACHER=$(VALUE)-${VALUE}
条件变量,根据SDK 、 Arch和Configration对设置进行条件化,例如:
// 指定 'Configration' 是'Debug
//指定'SDK'是模拟器,还有iphoneos*、macosx*等
//指定生效架构为'x86_64
OTHER_LDFLAGS[config=Debug][sdk=iphonesimulator*[arch=x86_64]= $(inherited) -framework "HYJADCrash"
注意!:在Xcode 11.4及以后版本,可以使用default ,来指定变量为空时的默认值:
1 I $(BUILD_SETTING_NAME:default=value)
总结:整个iOS工程,由workspace决定project的工作环境和关联关系,由project去管理资源,决定target的Configuration环境,由target根据Scheme和Configuration环境进行编译输出。由Scheme决定构建过程的配置环境与执行的任务,由Configuration对应的xcconfig决定编译过程的相关配置参数。
多环境配置
多环境是指,同一个project中,不同的target,不同的scheme,不同的xcconfig下,相同的代码执行不同的编译运行环境。
多环境配置的方式有多种,一般有以下两种。
1.多target的方式来配置多环境
2.配置xccongfig文件配置
日常项目中为了方便使用,都是采用的第二种xcconfig方式。cocoapods也是使用该方式。
例如:一般的项目开发,我们会分为,debug、bate、release版本。对于同一个project的代码,需要有3种编译运行环境,3种编译环境中,功能上会有所不同,连接的服务器接口不同,参数不同等。此时我们需要进行以下步骤
Release:最终上线发行的版本
Bate:上线公测或灰度测试的版本
Debug:内测版本
1.创建debug、bate、release 三个版本的.xcconfig
2.分别在三个xcconfig文件中设置对应的参数变量
3.因为在xcconfig中配置了一些非系统变量,则需要在对应的地方使用对应的变量。例如我设置了每个版本的App名称和不同的bundle id。则需要在info.plist文件里引用对应的变量。
4.创建bate版本的Configuration(系统会默认创建Debug和Release)
5.在三个版本的configuration中,选择对应的xcconfig文件
6.创建Bate、Debug、Release三个Scheme
7.在三个scheme中选择对应的configuration
8.选择对应的Scheme进行编译运行
总结:多环境配置的主要目的是,在同一套代码中,一些不同开发环境的数据、变量、基本信息和编译内容等都可以单独进行控制。而不是对代码进行侵入式的修改。这样既保证了环境的独立性又保证了编译或打包的直观性。