热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

iOS开发xconfig和script脚本使用详解

这篇文章主要为大家介绍了iOS开发xconfig和script脚本使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

引言

利用Xcode进行开发时需要进行很多build setting的设置以便能让项目按照设置的进行编译,同时有时候需要在编译时利用script脚本进行一些设置,本文主要介绍xconfig文件和script脚本在Xcode开发中使用。

Xcode编译

在使用xconfig时有几个关于Xcode的概念是需要理解的,这里我进行通俗简单的说明,同时需要知道Xcode在编译的过程中具体帮我们做了那几件事情。

Xcode target

在实际开发中一个Xcode创建的项目是可以有多个taget的,比如我们创建一个widgetXcode会自动新建一个target对应这个widget,也可以自己新建,同一个项目有多个target可以满足不同的测试场景,比如在前期开发阶段使用一个target,到UAT阶段使用另外一个target。一个target对应一个product,也就是编译后安装到手机上的项目,target定义了生成的唯一 product, 它将构建该product 所需的文件和处理这些文件所需的指令集整合进 build system 中,这些指令以 build settingbuild phases的形式存在,我们用xconfig文件来设置 build setting,同时将script脚本添加到build phases 中。

新建target

Xcode project

Xcode project 是一个仓库,该仓库包含了所有的文件,资源和用于生成一个或者多个software products 的信息,它包含一个或者多个targets,其中的每一个 target指明了如何生成 productsproject为其拥有的所有 targets定义了默认的build settings,例如project中默认包含debugrelease 两种build settings 当然,每一个 target能够制定其自己的 build settings,且targetbuild settings 会重写projectbuild settings

Xcode scheme

一个project可以有多个target,但是当前的target只能有一个,scheme就是用来确定当前的target的,并制定当前的target使用哪种configuration

新建configuration

打开项目编辑栏选择上面的progect同时选择info栏,可以看到Xcode默认添加了二个DebugReleaseconfiguration,点击做下角的+号按钮选择复制Debug或者Release其中一个configuration来新建并命名一个自己想取的名字,我这里命名为Mamba

Configuration文件的使用

平时手动的在Xcode中进行项目的一些build setting设置还是比较麻烦的,一个是需要在Xcode中进行搜索,另外一个是不好管理,例如需要在debug或者release下进行不同的设置的话就比较麻烦。利用Configuration文件来代替手动设置则更加的方便,直接新建Configuration Setting file类型文件,如下图所示:

利用Configuration设置不同的项目名

Configuration文件是可以继承的,一般先建立一个Common Configuration文件用来作为父类,为此新建一个名为CommonConfiguration文件,并加入如下代码:

APP_NAME = TestDemo

然后分别新建名为debugMambareleaseConfiguration文件,并加入如下代码:

  • debug
#include "Common.xcconfig"
APP_NAME = $(inherited)Debug
  • Mamba
#include "Common.xcconfig"
APP_NAME = $(inherited)Mamba
  • release
```Swift
#include "Common.xcconfig"
APP_NAME = $(inherited)Release

上面利用#include进行导入依赖的Configuration文件,并利用$(inherited)来引用依赖的Configuration文件中的变量。

Configuration文件中的语法一般是SETTING_NAME = VALUE,具体等式二边设置的值可见苹果官网.

设置Configuration

点击PROJECT导航栏并选择Info会发现多了一个上文我们添加的名为MambaConfiguration

点击左边的小三角箭头展开每个Configuration后可以设置项目的project级别的Configuration Filetarget级别的Configuration File,当然也可以默认不设置。分别设置三个Configuration下的project级别的Configuration FileBasetarget级别的Configuration File则为对应的Configuration File,如下图所示:

查看是否设置成功

点击TARGETS导航栏,选择Build Settings并选中AllLevels滑到最下面可看见APP_NAME的值设置如下:

这里需要解释一下几个设置的级别:

  • Resolved: 最后生效的值
  • Target: 显示在Target级别生效的值,Target级别的优先级是高于Project的,并且默认继承Project设置的值。
  • Project: 显示在Project级别生效的值,往常在XcodeGeneral设置的值就是这一级别的。
  • iOS Default : 显示iOS默认设置的值。

加上Configuration File后优先级顺序从低到高如下:

  • Platform defaults
  • Project.xcconfig file
  • Project file build settings
  • Target .xcconfig file
  • Target build settings

设置Info.plist

最后为了通过Configuration File来控制APP运行时名字的显示,需要在Info.plist中链接Bundle display name属性(没有的话需要新增)到我们上面设置的user-defined setting(APP_NAME) 上,为此修改Info.plistBundle display name的值为 $(APP_NAME)

测试是否生效

Scheme页面分别选择debugreleasemamba三中不同的Configuration环境运行APP成功的根据不同的Configtation设置不同的项目运行名字。

利用xconfig文件实现OC条件编译

在开发中经常需要进行条件编译,在OC中可以利用pch文件配合宏来实现,例如如下:

#ifdef DEBUG
#define BaseURL @"192.168.1.1:8080/appname/api"
#define PublicKEY @"QWE3R23WR09WURI220WR3TTY5ET3CR2X"
#else
#define BaseURL @"http://api.appname.com"
#define PublicKEY @"32GDG4575UB5M97O7M2X32RFH53QWT43"
#endif

通过在pch文件中利用条件编译定义不用的宏来实现项目的动态切换配置,上述宏定义一般定义在.pch中,通常.pch文件中定义的宏都比较杂乱,希望能单独放在一个独立的文件中,可以通过新建一个头文件env.h, 把上述宏定义放到env.h中,在需要使用的时候导入头文件即可,把环境参数单独放在一个独立的头文件中,更加简洁,职能更加专一,也便于维护但是这种做法还不是最好的,因为还需要手动导入头文件,而且生产环境参数和开发环境参数是放在同一个文件中而是不是独立分开的,要想独立分开并且使用时又不用导入头文件可以通过Xcode中的Configurations Setting Fil(.xcconfig)来解决,这应该是最优的实现方式。

xconfig文件的设置

在上面的Debug.xconfigMamba.xconfig文件中分别加入如下代码:

  • Debug.xconfig
WEBSERVICE_URL = @"www.baidu.com"
  • Mamba.xconfig
WEBSERVICE_URL = @"www.jd.com"

这样只是自定义了一个Build Setting变量,不能代码里像使用宏那样使用,Xcode是支持利用GCC_PREPROCESSOR_DEFINITIONS在定义宏的,在Common.xconfig文件中加入如下代码:

GCC_PREPROCESSOR_DEFINITIOnS= $(inherited) WEBSERVICE_URL='$(WEBSERVICE_URL)'

TARGET导航栏中Preprocessor Macros即可看见我们定义的宏。

代码使用

可以在代码中直接使用定义的宏,当切换Configuration时则会根据.xconfig文件输入不同的打印。

- (void)viewDidLoad {
    [super viewDidLoad];
    NSLog(@"-----------%@-------------",WEBSERVICE_URL);
}

使用#include语法来包含其他配置文件,如#include "Common.xcconfig", 最好是放在文件的最后面,放在文件的开头也可以。Common.xconfig中第一个键的配置必须有:GCC_PREPROCESSOR_DEFINITIOnS= $(inherited),没有Xcode会报错,暴露自定义键时的语法:宏名='$(key)',在代码或其他地方使用宏名来引用,'$(key)':通过key来指定每个模式下的对应的自定义键的名字,通常将宏的名字和key的名字保持一致, 注意 等号前后一定不能有空,Common.xconfig中第一个keyGCC_PREPROCESSOR_DEFINITIOnS= $(inherited) 后面跟自定义的key,注意在第一个key后面跟上自己定义的key的时候一定不要回车换行,敲一个空格,然后在同一行后面追加就行了,换行会编译错误, 不能换行,不能换行,不能换行!

Swift中条件编译的实现

Swift中是不支持通过GCC_PREPROCESSOR_DEFINITIONS来定义宏的,但是可以通过定义Custom Flags进行定义,这里介绍另外一种方法,还是通过.xconfig文件进行获取我们需要的宏。前面我们通过info.plist获取到了.xconfig文件中自定义的变量,再次我们同样通过info.plist来获取自定义的变量的值来当做宏使用,首先在info.plist中新建一个WEBSERVICE_URL变量,并设置值为'$(WEBSERVICE_URL)',由于需要解析info.plist中的变量,再次封装一个config.swift的类用来解析:

import Foundation
enum Config {
  static func stringValue(forKey key: String) -> String {
    guard let value = Bundle.main.object(forInfoDictionaryKey: key) as? String else {
      fatalError("Invalid value or undefined key")
    }
    return value
  }
}

代码使用

import UIKit
class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        print(Config.stringValue(forKey:"WEBSERVICE_URL"))
    }
}

相比较于OC版本的是不能直接定义宏,需要通过在info.plist定义后并通过方法取出值后才能使用,稍微麻烦了一点。

script的使用

上文我们已经知道xconfig文件的使用,其实在编译之前不只是变量的自定义或者获取项目的一些默认参数,还可以在获取这些参数的基础上,将这些参数作为script脚本的变量来做一些更有意义的事情,Xcode是支持在编译之前链接script脚本的。

script的初步认识

脚本一般来说就是可执行的二进制文件,下面先制作一个简单的脚本加深认知(实例代码采用Swift),首先新建一个名为HelloXcode.swift文件,加入如下代码:

import Foundation
@main
enum MyScript {
  static func main() {
    print("Hello Xcode")
  }
}

下面我们用终端来编译上面的HelloXcode.swift文件,cd到文件所在的目录执行以下代码:

xcrun --sdk macosx swiftc -parse-as-library HelloXcode.swift -o CompiledScript

利用macOS SDK来编译HelloXcode.swift并输出名为CompiledScript的二进制脚本文件,此时可以直接在当前目录利用./CompiledScript执行该脚本文件,会直接输出打印HelloXcode。为了在Xcode编译阶段就能运行脚本,我们需要将脚本插入到XcodeBuild Phases中,首先我们先新建一个Build Phases如下所示:

Xcode中的Build Phases选项卡是Xcode build项目的中心,Xcode在编译项目时其实帮我们做了如下几件事情:

  • 确定项目的一些依赖并编译
  • 编译项目的代码
  • 链接上面编译的依赖文件
  • 复制资源文件例如图片等到项目bundle中

这里我们是要在项目编译开始之前就运行脚本,所以需要调整新增加的Build Phases的顺序,直接拖到Denpencies下面,如下图所示:


点击刚刚新加的Build Phases可以重命名,展开后加入如下代码:


下面的Input Files可以理解为脚本的变量,这里将HelloXcode.swift相对工程文件所在的路$SCRIPT_INPUT_FILE_0进行引用,$(SRCROOT)代表工程文件所在的目录,运行项目在build log(不是打印台)会看见如下输出:

script的实际运用

利用script来实现每当build的时候改变 Info.plistBundle version或者Bundle version string (short)的值,新建一个IncBuildNumber.swift 文件,加入如下代码:

import Foundation
@main
enum IncBuildNumber {
  static func main() {
    guard let infoFile = ProcessInfo.processInfo
      .environment["INFOPLIST_FILE"]
    else {
      return
    }
    guard let projectDir = ProcessInfo.processInfo.environment["SRCROOT"] else {
      return
    }
    if var dict = NSDictionary(contentsOfFile:
      projectDir + "/" + infoFile) as? [String: Any] {
      guard 
        let currentVersiOnString= dict["CFBundleShortVersionString"]
          as? String,
        let currentBuildNumberString = dict["CFBundleVersion"] as? String,
        let currentBuildNumber = Int(currentBuildNumberString)
      else {
        return
        }
      dict["CFBundleVersion"] = "\(currentBuildNumber + 1)"
      if ProcessInfo.processInfo.environment["CONFIGURATION"] == "Release" {
        var versiOnComponents= currentVersionString
          .components(separatedBy: ".")
        let lastCompOnent= (Int(versionComponents.last ?? "1") ?? 1)
        versionComponents[versionComponents.endIndex - 1] = 
          "\(lastComponent + 1)"
        dict["CFBundleShortVersionString"] = versionComponents
          .joined(separator: ".")
      }
      (dict as NSDictionary).write(
        toFile: projectDir + "/" + infoFile, 
        atomically: true)
    }
  }
}

Xcode在执行run script phase时会通过环境变量environment variables来共享build settings,可以将环境变量在这里理解为全局变量,这里通过环境变量拿到了info.plist中的CFBundleShortVersionStringCFBundleVersion变量,并根据CONFIGURATION配置的是Release还是Debug来修改对应的BundleVersion,至此每当build时都会改变相应的BuildVersion值。

总结

本文主要介绍了利用xconfig文件如何进行项目的动态配置,并进行了实际的演示,同时介绍了scriptXcode中编译的基本使用,并配合xconfig文件能让Xcode在编译前做更多有意义的事情,更多关于iOS使用xconfig script脚本的资料请关注其它相关文章!


推荐阅读
  • Android Studio Bumblebee | 2021.1.1(大黄蜂版本使用介绍)
    本文介绍了Android Studio Bumblebee | 2021.1.1(大黄蜂版本)的使用方法和相关知识,包括Gradle的介绍、设备管理器的配置、无线调试、新版本问题等内容。同时还提供了更新版本的下载地址和启动页面截图。 ... [详细]
  • 本文介绍了在CentOS上安装Python2.7.2的详细步骤,包括下载、解压、编译和安装等操作。同时提供了一些注意事项,以及测试安装是否成功的方法。 ... [详细]
  • Flutter App 中创建模块并且依赖 Flutter
    在FlutterApp中打开对应的Android工程;并且向Android原生工程添加一个AndroidModule模块,并且在工程根settings. ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文介绍了Hyperledger Fabric外部链码构建与运行的相关知识,包括在Hyperledger Fabric 2.0版本之前链码构建和运行的困难性,外部构建模式的实现原理以及外部构建和运行API的使用方法。通过本文的介绍,读者可以了解到如何利用外部构建和运行的方式来实现链码的构建和运行,并且不再受限于特定的语言和部署环境。 ... [详细]
  • 树莓派语音控制的配置方法和步骤
    本文介绍了在树莓派上实现语音控制的配置方法和步骤。首先感谢博主Eoman的帮助,文章参考了他的内容。树莓派的配置需要通过sudo raspi-config进行,然后使用Eoman的控制方法,即安装wiringPi库并编写控制引脚的脚本。具体的安装步骤和脚本编写方法在文章中详细介绍。 ... [详细]
  • GreenDAO快速入门
    前言之前在自己做项目的时候,用到了GreenDAO数据库,其实对于数据库辅助工具库从OrmLite,到litePal再到GreenDAO,总是在不停的切换,但是没有真正去了解他们的 ... [详细]
  • macOS Big Sur全新设计大版本更新,10+个值得关注的新功能
    本文介绍了Apple发布的新一代操作系统macOS Big Sur,该系统采用全新的界面设计,包括图标、应用界面、程序坞和菜单栏等方面的变化。新系统还增加了通知中心、桌面小组件、强化的Safari浏览器以及隐私保护等多项功能。文章指出,macOS Big Sur的设计与iPadOS越来越接近,结合了去年iPadOS对鼠标的完善等功能。 ... [详细]
  • 本文整理了Java中org.gwtbootstrap3.client.ui.Icon.addDomHandler()方法的一些代码示例,展示了Icon.ad ... [详细]
  • 今日份分享:Flutter自定义之旋转木马
    今日份分享:Flutter自定义之旋转木马-先上图,带你回到童年时光:效果分析子布局按照圆形顺序放置且平分角度子布局旋转、支持手势滑动旋转、快速滑动抬手继续旋转、自动旋转支持X轴旋 ... [详细]
  • 大坑|左上角_pycharm连接服务器同步写代码(图文详细过程)
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了pycharm连接服务器同步写代码(图文详细过程)相关的知识,希望对你有一定的参考价值。pycharm连接服务 ... [详细]
  • ihaveusedthedelphidatabindingwizardwithmyxmlfile,andeverythingcompilesandrunsfine. ... [详细]
  • 在一对一直播源码使用过程中,有时会出现软键盘切换闪屏问题,就是当切换表情的时候屏幕会跳动,因此要对一对一直播源码表情面板无缝切换进行优化。 ... [详细]
author-avatar
淘宝杂谈网z
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有