欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

iOS開發(fā)xconfig和script腳本使用詳解

 更新時間:2022年09月08日 16:24:40   作者:MambaYong  
這篇文章主要為大家介紹了iOS開發(fā)xconfig和script腳本使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

引言

利用Xcode進行開發(fā)時需要進行很多build setting的設(shè)置以便能讓項目按照設(shè)置的進行編譯,同時有時候需要在編譯時利用script腳本進行一些設(shè)置,本文主要介紹xconfig文件和script腳本在Xcode開發(fā)中使用。

Xcode編譯

在使用xconfig時有幾個關(guān)于Xcode的概念是需要理解的,這里我進行通俗簡單的說明,同時需要知道Xcode在編譯的過程中具體幫我們做了那幾件事情。

Xcode target

在實際開發(fā)中一個Xcode創(chuàng)建的項目是可以有多個taget的,比如我們創(chuàng)建一個widgetXcode會自動新建一個target對應(yīng)這個widget,也可以自己新建,同一個項目有多個target可以滿足不同的測試場景,比如在前期開發(fā)階段使用一個target,到UAT階段使用另外一個target。一個target對應(yīng)一個product,也就是編譯后安裝到手機上的項目,target定義了生成的唯一 product, 它將構(gòu)建該product 所需的文件和處理這些文件所需的指令集整合進 build system 中,這些指令以 build settingbuild phases的形式存在,我們用xconfig文件來設(shè)置 build setting,同時將script腳本添加到build phases 中。

新建target

Xcode project

Xcode project 是一個倉庫,該倉庫包含了所有的文件,資源和用于生成一個或者多個software products 的信息,它包含一個或者多個targets,其中的每一個 target指明了如何生成 products。project為其擁有的所有 targets定義了默認的build settings,例如project中默認包含debugrelease 兩種build settings 當(dāng)然,每一個 target能夠制定其自己的 build settings,且targetbuild settings 會重寫projectbuild settings

Xcode scheme

一個project可以有多個target,但是當(dāng)前的target只能有一個,scheme就是用來確定當(dāng)前的target的,并制定當(dāng)前的target使用哪種configuration

新建configuration

打開項目編輯欄選擇上面的progect同時選擇info欄,可以看到Xcode默認添加了二個DebugReleaseconfiguration,點擊做下角的+號按鈕選擇復(fù)制Debug或者Release其中一個configuration來新建并命名一個自己想取的名字,我這里命名為Mamba。

Configuration文件的使用

平時手動的在Xcode中進行項目的一些build setting設(shè)置還是比較麻煩的,一個是需要在Xcode中進行搜索,另外一個是不好管理,例如需要在debug或者release下進行不同的設(shè)置的話就比較麻煩。利用Configuration文件來代替手動設(shè)置則更加的方便,直接新建Configuration Setting file類型文件,如下圖所示:

利用Configuration設(shè)置不同的項目名

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進行導(dǎo)入依賴的Configuration文件,并利用$(inherited)來引用依賴的Configuration文件中的變量。

Configuration文件中的語法一般是SETTING_NAME = VALUE,具體等式二邊設(shè)置的值可見蘋果官網(wǎng).

設(shè)置Configuration

點擊PROJECT導(dǎo)航欄并選擇Info會發(fā)現(xiàn)多了一個上文我們添加的名為MambaConfiguration。

點擊左邊的小三角箭頭展開每個Configuration后可以設(shè)置項目的project級別的Configuration Filetarget級別的Configuration File,當(dāng)然也可以默認不設(shè)置。分別設(shè)置三個Configuration下的project級別的Configuration FileBasetarget級別的Configuration File則為對應(yīng)的Configuration File,如下圖所示:

查看是否設(shè)置成功

點擊TARGETS導(dǎo)航欄,選擇Build Settings并選中AllLevels滑到最下面可看見APP_NAME的值設(shè)置如下:

這里需要解釋一下幾個設(shè)置的級別:

  • Resolved: 最后生效的值
  • Target: 顯示在Target級別生效的值,Target級別的優(yōu)先級是高于Project的,并且默認繼承Project設(shè)置的值。
  • Project: 顯示在Project級別生效的值,往常在XcodeGeneral設(shè)置的值就是這一級別的。
  • iOS Default : 顯示iOS默認設(shè)置的值。

加上Configuration File后優(yōu)先級順序從低到高如下:

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

設(shè)置Info.plist

最后為了通過Configuration File來控制APP運行時名字的顯示,需要在Info.plist中鏈接Bundle display name屬性(沒有的話需要新增)到我們上面設(shè)置的user-defined setting(APP_NAME) 上,為此修改Info.plistBundle display name的值為 $(APP_NAME)

測試是否生效

Scheme頁面分別選擇debug,releasemamba三中不同的Configuration環(huán)境運行APP成功的根據(jù)不同的Configtation設(shè)置不同的項目運行名字。

利用xconfig文件實現(xiàn)OC條件編譯

在開發(fā)中經(jīng)常需要進行條件編譯,在OC中可以利用pch文件配合宏來實現(xiàn),例如如下:

#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文件中利用條件編譯定義不用的宏來實現(xiàn)項目的動態(tài)切換配置,上述宏定義一般定義在.pch中,通常.pch文件中定義的宏都比較雜亂,希望能單獨放在一個獨立的文件中,可以通過新建一個頭文件env.h, 把上述宏定義放到env.h中,在需要使用的時候?qū)腩^文件即可,把環(huán)境參數(shù)單獨放在一個獨立的頭文件中,更加簡潔,職能更加專一,也便于維護但是這種做法還不是最好的,因為還需要手動導(dǎo)入頭文件,而且生產(chǎn)環(huán)境參數(shù)和開發(fā)環(huán)境參數(shù)是放在同一個文件中而是不是獨立分開的,要想獨立分開并且使用時又不用導(dǎo)入頭文件可以通過Xcode中的Configurations Setting Fil(.xcconfig)來解決,這應(yīng)該是最優(yōu)的實現(xiàn)方式。

xconfig文件的設(shè)置

在上面的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導(dǎo)航欄中Preprocessor Macros即可看見我們定義的宏。

代碼使用

可以在代碼中直接使用定義的宏,當(dāng)切換Configuration時則會根據(jù).xconfig文件輸入不同的打印。

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

使用#include語法來包含其他配置文件,如#include "Common.xcconfig", 最好是放在文件的最后面,放在文件的開頭也可以。Common.xconfig中第一個鍵的配置必須有:GCC_PREPROCESSOR_DEFINITIONS = $(inherited),沒有Xcode會報錯,暴露自定義鍵時的語法:宏名='$(key)',在代碼或其他地方使用宏名來引用,'$(key)':通過key來指定每個模式下的對應(yīng)的自定義鍵的名字,通常將宏的名字和key的名字保持一致, 注意 等號前后一定不能有空,Common.xconfig中第一個keyGCC_PREPROCESSOR_DEFINITIONS = $(inherited) 后面跟自定義的key,注意在第一個key后面跟上自己定義的key的時候一定不要回車換行,敲一個空格,然后在同一行后面追加就行了,換行會編譯錯誤, 不能換行,不能換行,不能換行!

Swift中條件編譯的實現(xiàn)

Swift中是不支持通過GCC_PREPROCESSOR_DEFINITIONS來定義宏的,但是可以通過定義Custom Flags進行定義,這里介紹另外一種方法,還是通過.xconfig文件進行獲取我們需要的宏。前面我們通過info.plist獲取到了.xconfig文件中自定義的變量,再次我們同樣通過info.plist來獲取自定義的變量的值來當(dāng)做宏使用,首先在info.plist中新建一個WEBSERVICE_URL變量,并設(shè)置值為'$(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的使用

上文我們已經(jīng)知道xconfig文件的使用,其實在編譯之前不只是變量的自定義或者獲取項目的一些默認參數(shù),還可以在獲取這些參數(shù)的基礎(chǔ)上,將這些參數(shù)作為script腳本的變量來做一些更有意義的事情,Xcode是支持在編譯之前鏈接script腳本的。

script的初步認識

腳本一般來說就是可執(zhí)行的二進制文件,下面先制作一個簡單的腳本加深認知(實例代碼采用Swift),首先新建一個名為HelloXcode.swift文件,加入如下代碼:

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

下面我們用終端來編譯上面的HelloXcode.swift文件,cd到文件所在的目錄執(zhí)行以下代碼:

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

利用macOS SDK來編譯HelloXcode.swift并輸出名為CompiledScript的二進制腳本文件,此時可以直接在當(dāng)前目錄利用./CompiledScript執(zhí)行該腳本文件,會直接輸出打印HelloXcode。為了在Xcode編譯階段就能運行腳本,我們需要將腳本插入到XcodeBuild Phases中,首先我們先新建一個Build Phases如下所示:

Xcode中的Build Phases選項卡是Xcode build項目的中心,Xcode在編譯項目時其實幫我們做了如下幾件事情:

  • 確定項目的一些依賴并編譯
  • 編譯項目的代碼
  • 鏈接上面編譯的依賴文件
  • 復(fù)制資源文件例如圖片等到項目bundle中

這里我們是要在項目編譯開始之前就運行腳本,所以需要調(diào)整新增加的Build Phases的順序,直接拖到Denpencies下面,如下圖所示:


點擊剛剛新加的Build Phases可以重命名,展開后加入如下代碼:


下面的Input Files可以理解為腳本的變量,這里將HelloXcode.swift相對工程文件所在的路$SCRIPT_INPUT_FILE_0進行引用,$(SRCROOT)代表工程文件所在的目錄,運行項目在build log(不是打印臺)會看見如下輸出:

script的實際運用

利用script來實現(xiàn)每當(dāng)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)
    }
  }
}

當(dāng)Xcode在執(zhí)行run script phase時會通過環(huán)境變量environment variables來共享build settings,可以將環(huán)境變量在這里理解為全局變量,這里通過環(huán)境變量拿到了info.plist中的CFBundleShortVersionStringCFBundleVersion變量,并根據(jù)CONFIGURATION配置的是Release還是Debug來修改對應(yīng)的BundleVersion,至此每當(dāng)build時都會改變相應(yīng)的BuildVersion值。

總結(jié)

本文主要介紹了利用xconfig文件如何進行項目的動態(tài)配置,并進行了實際的演示,同時介紹了scriptXcode中編譯的基本使用,并配合xconfig文件能讓Xcode在編譯前做更多有意義的事情,更多關(guān)于iOS使用xconfig script腳本的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • iOS中NSThread使用示例詳解

    iOS中NSThread使用示例詳解

    這篇文章主要為大家介紹了iOS中NSThread使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-10-10
  • IOS LaunchScreen設(shè)置啟動圖片與啟動頁停留時間詳解

    IOS LaunchScreen設(shè)置啟動圖片與啟動頁停留時間詳解

    這篇文章主要介紹了IOS LaunchScreen設(shè)置啟動圖片與啟動頁停留時間詳解的相關(guān)資料,需要的朋友可以參考下
    2017-02-02
  • iOS開發(fā)Masonry與Frame布局差異示例詳解

    iOS開發(fā)Masonry與Frame布局差異示例詳解

    這篇文章主要為大家介紹了iOS開發(fā)Masonry與Frame布局差異示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-11-11
  • 詳解iOS11關(guān)于導(dǎo)航欄問題

    詳解iOS11關(guān)于導(dǎo)航欄問題

    本篇文章主要介紹了詳解iOS11關(guān)于導(dǎo)航欄問題,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-10-10
  • iOS中UITableView使用的常見問題總結(jié)

    iOS中UITableView使用的常見問題總結(jié)

    這篇文章主要總結(jié)了iOS中UITableView使用的常見問題,其中包括如何設(shè)置headerView以及其高度、去掉多余cell的分割線 以及如何設(shè)置section數(shù)、行數(shù)等一系列的問題,文中介紹的更詳細,需要的朋友們下面來一起看看詳細介紹吧。
    2017-03-03
  • 詳解iOS視頻播放方式

    詳解iOS視頻播放方式

    本篇文章給大家詳細講述了詳解iOS視頻播放方式以及第三方開元播放軟件的使用,學(xué)習(xí)下吧。
    2017-12-12
  • 快速解決iOS10不能跳轉(zhuǎn)系統(tǒng)WiFi列表的問題

    快速解決iOS10不能跳轉(zhuǎn)系統(tǒng)WiFi列表的問題

    下面小編就為大家?guī)硪黄焖俳鉀QiOS10不能跳轉(zhuǎn)系統(tǒng)WiFi列表的問題。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-04-04
  • iOS App中數(shù)據(jù)管理框架Core Data的基本數(shù)據(jù)操作教程

    iOS App中數(shù)據(jù)管理框架Core Data的基本數(shù)據(jù)操作教程

    Core Data框架能夠為我們提供比操作SQL關(guān)系型數(shù)據(jù)庫更簡單的數(shù)據(jù)管理方式,而且內(nèi)置于Xcode中配合IDE操作十分方便,下面我們就來看一下iOS App中數(shù)據(jù)管理框架Core Data的基本數(shù)據(jù)操作教程
    2016-06-06
  • iOS實現(xiàn)一個簡易日歷代碼

    iOS實現(xiàn)一個簡易日歷代碼

    本篇文章主要介紹了iOS實現(xiàn)一個簡易日歷代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-03-03
  • Stack?View自定義間隙減少約束的數(shù)量

    Stack?View自定義間隙減少約束的數(shù)量

    這篇文章主要為大家介紹了Stack?View自定義間隙減少約束的數(shù)量示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-08-08

最新評論