当前位置:首页 > 站长资讯 > 正文内容

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

yc8881年前 (2022-11-22)站长资讯256

10067.jpg

这篇文章主要为大家介绍了iOS开发xconfig和script脚本使用详解,有需要的朋友可以借鉴参考下。

目录
  • 引言

  • Xcode编译

    • Xcode target

    • Xcode project

    • Xcode scheme

  • 新建configuration

    • Configuration文件的使用

    • 利用Configuration设置不同的项目名

    • 设置Configuration

    • 查看是否设置成功

    • 设置Info.plist

    • 测试是否生效

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

    • xconfig文件的设置

  • Swift中条件编译的实现

    • script的使用

      • script的初步认识

      • 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 setting 和 build phases的形式存在,我们用xconfig文件来设置 build setting,同时将script脚本添加到build phases 中。


      新建target


      Xcode project

      Xcode project 是一个仓库,该仓库包含了所有的文件,资源和用于生成一个或者多个software products 的信息,它包含一个或者多个targets,其中的每一个 target指明了如何生成 productsproject为其拥有的所有 targets定义了默认的build settings,例如project中默认包含debug 和release 两种build settings 当然,每一个 target能够制定其自己的 build settings,且target 的build settings 会重写project 的 build 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 Foundationenum 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 UIKitclass 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@mainenum 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@mainenum 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在编译前做更多有意义的事情


      本站发布的内容若侵犯到您的权益,请邮件联系站长删除,我们将及时处理!


      从您进入本站开始,已表示您已同意接受本站【免责声明】中的一切条款!


      本站大部分下载资源收集于网络,不保证其完整性以及安全性,请下载后自行研究。


      本站资源仅供学习和交流使用,版权归原作者所有,请勿商业运营、违法使用和传播!请在下载后24小时之内自觉删除。


      若作商业用途,请购买正版,由于未及时购买和付费发生的侵权行为,使用者自行承担,概与本站无关。


      本文链接:https://www.10zhan.com/zhanzhang/10067.html

      标签: ios
      分享给朋友:

      “iOS开发xconfig和script脚本使用详解” 的相关文章

      【说站】宝塔站点日志文件过大怎么办?网站日志切割教程

      【说站】宝塔站点日志文件过大怎么办?网站日志切割教程

      宝塔面板日志文件过大的原因?宝塔面板的网站日志文件默认是生成一个日志文件,然后系统每天不断的对这个文件进行写入操作,这样日子长了,这个日志文件就会越来越大,几百兆、几个G都是蛮正常的,这样对于我们分析...

      【说站】Win10专业版如何激活?Win10激活工具

      【说站】Win10专业版如何激活?Win10激活工具

      本人用的Win10专业版一直用的好好地,今天桌面右下方就提示“激活Windows 转到设置以激活Windows”,因为一直用的是盗版Windows 10,出现这样的提示也蛮正常,没得办法,见招拆招,在...

      【说站】excel筛选两列数据中的重复数据并排序

      【说站】excel筛选两列数据中的重复数据并排序

      如果靠人眼来一个个的对比excel的两列数据来去重的话,数据量少还能勉强对比一下,如果几千、几万条数据肯定就需要进行程式化处理,excel对于这个问题给我们提供了很方便的解决方案,这里主要用到exce...

      【说站】Excel如何快速删除空行?WPS删除excel空白行

      【说站】Excel如何快速删除空行?WPS删除excel空白行

      站长我经常会处理excel文档,之前介绍过Microsoft Office excel文档删除空行的办法,今天介绍WPS Office下面的excel如何删除空白行。方法一:筛选  选中数据所在的那一...

      【说站】宝塔如何按日期每天生成一个网站日志文件

      【说站】宝塔如何按日期每天生成一个网站日志文件

      宝塔面板默认的会按照nginx.conf的配置生成在/www/wwwlogs目录下面生成一个网站访问日志和一个网站错误日志,每当有新的记录时系统会不断的对这两个文件进行写入操作,但随着访问量的增长,日...

      【说站】WordPress网站文章ID不连续如何解决?

      【说站】WordPress网站文章ID不连续如何解决?

      对于WordPress网站文章ID不连续的问题困扰了我很久,今天将WordPress文章ID不连续的原因和具体解决办法做详细的说明。WordPress文章ID不连续的原因:用WordPress做网站的...