程序調(diào)試 (五) —— 使用Build Configurations 和 .xcconfig 構(gòu)建你的App(一)

版本記錄

版本號 時間
V1.0 2021.06.09 星期三

前言

程序總會有bug嘹承,如果有好的調(diào)試技巧和方法浸策,那么就是事半功倍,這個專題專門和大家分享下和調(diào)試相關(guān)的技巧乔询。希望可以幫助到大家谎砾。感興趣的可以看下面幾篇文章逢倍。
1. 程序調(diào)試 (一) —— App Crash的調(diào)試和解決示例(一)
2. 程序調(diào)試 (二) —— Xcode Simulator的高級功能(一)
3. 程序調(diào)試 (三) —— Xcode Simulator的高級功能(二)
4. 程序調(diào)試 (四) —— Xcode內(nèi)存管理(一)

開始

首先看下主要內(nèi)容:

使用 Xcode build settings.xcconfig文件以不同的構(gòu)建配置(build configurations)更改應用程序的設置和圖標。內(nèi)容來自翻譯景图。

下面看下寫作環(huán)境:

Swift 5, iOS 14, Xcode 12

下面就是正文啦较雕。

Debug, test, release —— 這些是大多數(shù)應用程序經(jīng)歷的階段。 在每個階段挚币,應用程序都有不同的構(gòu)建設置亮蒋、定義和常量。 開發(fā)人員使用debug后端 URL 和設置構(gòu)建應用程序忘晤。 測試人員使用類似生產(chǎn)的設置測試 beta 版本宛蚓。 客戶使用具有最終生產(chǎn)設置的應用程序。

Xcode 中跨不同環(huán)境管理這些設置非常耗時——更不用說當您有多個targets時增加的工作了设塔。 幸運的是凄吏,Apple 提供了一種更好的方式來處理這些設置:Xcode build configuration files, or .xcconfig files远舅。

在本教程中,您將:

  • 使用 Xcode 構(gòu)建配置文件痕钢。
  • 管理跨多個環(huán)境和targets的構(gòu)建設置图柏。
  • 從代碼訪問構(gòu)建設置。

打開起始項目任连。 構(gòu)建并運行蚤吹。

您將使用的應用程序 NinjaCounter 可幫助生物學家和愛好者計算海龜孵化的數(shù)量。 該應用程序有一個視圖:CounterView.swift随抠,用戶可以在其中記錄幼龜裁着。

NinjaCounter 組中,您會發(fā)現(xiàn)以下內(nèi)容:

  • Hatchling:一個簡單的結(jié)構(gòu)拱她,具有孵化記錄屬性二驰。
  • UserDefaultsHelper:一個 UserDefaults 助手,提供存儲和加載孵化記錄的方法秉沼。

構(gòu)建并運行桶雀。 在tag text field中,輸入 Leonardo唬复。 點擊+ Hatchling按鈕矗积。

這樣,您就創(chuàng)建了一個帶有孵化標簽和孵化時間的新記錄敞咧。

現(xiàn)在您已經(jīng)了解了入門項目的要點棘捣,您將設置app widget


Setting Up Widget with App Group

打開 Widget.swift 并查看代碼妄均。 它創(chuàng)建了一個簡單的widget柱锹,顯示計數(shù)的孵化數(shù)量和報告的最后一個孵化的標簽。

getTimeline(in:completion:) 中丰包,widget使用 UserDefaultsHelpergetRecordsCount()getRecords()UserDefaults 獲取數(shù)據(jù)。

選擇 WidgetExtension scheme壤巷。 構(gòu)建并運行邑彪。

目前,即使您剛剛錄制了 Leonardo胧华,該widget也不顯示任何數(shù)據(jù)寄症。 這是因為擴展程序無權(quán)訪問應用程序的 UserDefaults。 要解決此問題矩动,您需要將應用程序和小部件添加到app group有巧。

在項目導航器中選擇 NinjaCounter 項目以顯示Project Editor。 選擇 NinjaCounter target悲没。 打開Signing & Capabilities選項卡篮迎。

選擇development team進行簽名。

Bundle Identifier更改為您獨有的內(nèi)容,例如 com.myorg.NinjaCounter甜橱。 請記住這一點逊笆,因為您將再次需要它。

單擊+ Capability岂傲。 雙擊App Groups难裆。

現(xiàn)在您已將App Groups添加到capabilities中,單擊 + 按鈕創(chuàng)建app group镊掖。 您將看到輸入組名稱的提示乃戈。

輸入group,單擊OK亩进。

現(xiàn)在症虑,對 Widget Extension target執(zhí)行相同的步驟。 確保bundle identifier.widget 結(jié)尾镐侯,但使用您為主應用程序創(chuàng)建的相同app group侦讨。 這允許在主機應用程序和widget extension之間共享數(shù)據(jù)。

現(xiàn)在您已經(jīng)創(chuàng)建了App Group并將targets添加到其中苟翻,是時候讓應用程序組訪問 UserDefaults套件了韵卤。

打開 UserDefaultsHelper.swift 并將defaults聲明替換為:

static private let defaults = UserDefaults(
  suiteName: "<#the app group name you defined#>")
  ?? .standard

使用此代碼,您可以確保應用從app group共享的 UserDefaults套件中保存和讀取數(shù)據(jù)崇猫。 這允許widget訪問孵化數(shù)據(jù)沈条。

active scheme更改為 NinjaCounter。 構(gòu)建并運行诅炉。

您添加的記錄不再存在蜡歹,因為您使用的是不同的 UserDefaults 套件。 再次加入Leonardo涕烧!

active scheme更改為WidgetExtention月而。 構(gòu)建并運行。

您現(xiàn)在可以看到widget顯示添加的記錄议纯。 恭喜父款!

在下一部分中,您將探索 Xcode 中的構(gòu)建設置瞻凤。


Demystifying Build Settings and Build Configurations in Xcode

在本節(jié)中憨攒,您將看到 Xcode 如何顯示和解析構(gòu)建設置。 打開項目編輯器阀参。 找到TARGETS列表肝集。 選擇 NinjaCounter 作為app target

選擇Build Settings選項卡蛛壳。 選擇 AllLevels 構(gòu)建設置過濾器選項杏瞻。

在這里所刀,您可以看到app target的構(gòu)建設置。 構(gòu)建設置分為四列伐憾,顯示不同范圍內(nèi)的設置值勉痴。

  • Resolved:解析優(yōu)先級后的實際值。
  • NinjaCounter (target):顯示在target級別設置的值树肃。 target構(gòu)建設置的優(yōu)先級高于project的優(yōu)先級蒸矛。 默認情況下,targetproject構(gòu)建設置繼承值胸嘴。
  • Ninja Counter (project):顯示在project的構(gòu)建設置中設置的值雏掠。 常規(guī)構(gòu)建設置在項目project級別可用,其他僅適用于target劣像。
  • iOS Default:顯示設置的 iOS 默認值乡话。

注意:構(gòu)建設置遵循以下優(yōu)先級,從低到高:

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

選擇 WidgetExtension target耳奕。 查看構(gòu)建設置绑青。

您可以在widget’s target level看到相同的設置。

Settings有多個值屋群,每個Build Configuration一個闸婴。 例如,查看Base SDK芍躏。 構(gòu)建配置就像一個環(huán)境邪乍。

您可以在項目級別全局定義Build ConfigurationsXcode為您創(chuàng)建兩個配置:Debug and Release对竣。

對于這些環(huán)境庇楞,構(gòu)建設置的默認值是不同的。 例如否纬,Clang Optimization LevelDebug 中設置為 None -O0吕晌,讓您調(diào)試和檢查代碼。 同時临燃,在 Release 中聂使,它默認為 Fastest, Smallest -Os 以實現(xiàn)最大的代碼優(yōu)化和最小的可執(zhí)行文件大小。

現(xiàn)在您已經(jīng)介紹了build settings谬俄,是時候回顧一下targets and schemes了。


Understanding Targets and Schemes

target指定單個產(chǎn)品及其構(gòu)建設置和文件弃理。 目標可以是應用程序溃论、擴展程序、框架痘昌、iMessage 應用程序钥勋、應用程序剪輯等炬转。

創(chuàng)建小widget時,Xcode 創(chuàng)建了一個新target算灸。 您為應用程序和widget target配置了開發(fā)團隊和功能扼劈。

Apple 將 Xcode scheme定義如下:“An Xcode scheme defines a collection of targets to build, a configuration to use when building, and a collection of tests to execute.”

創(chuàng)建一個新target會自動創(chuàng)建一個與之配套的新scheme

要查看此內(nèi)容菲驴,請單擊活動方案荐吵。 單擊Edit Scheme…

專業(yè)提示:通過按住 Option 鍵單擊active scheme赊瞬,直接進入scheme editor先煎,無需通過菜單。

您將看到scheme editor

例如巧涧,WidgetExtention scheme定義了 Xcode 將如何build, run, test, profile, analyze and archive widget target薯蝎。 它還定義了要與這些操作一起使用的構(gòu)建配置。

您可以看到 Run 默認為 Debug 配置谤绳,而 Archive 默認為 Release占锯。 Build Configuration下拉菜單是您更改所選構(gòu)建配置的地方。

關(guān)閉scheme editor缩筛。 接下來消略,您將為臨時環(huán)境創(chuàng)建一個新的構(gòu)建配置。


Creating a Staging Environment Configuration

要配置和創(chuàng)建應用程序的測試構(gòu)建歪脏,您需要一個暫存構(gòu)建配置疑俭。

打開Project Editor并選擇 NinjaCounter PROJECT。 打開Info選項卡婿失。

這是您定義構(gòu)建配置的地方钞艇。 它們是全局的,并且在targets之間共享豪硅。 單擊 + 添加一個新的哩照。

選擇Duplicate “Debug” Configuration。 將新配置命名為 Staging懒浮。

您將看到新的Staging配置飘弧。 選擇 NinjaCounter target并切換到 Build Settings 選項卡。

這些設置現(xiàn)在具有新構(gòu)建配置的新值砚著。 您從 Debug 復制了build configuration次伶,因此它們具有相同的值。

現(xiàn)在您已經(jīng)創(chuàng)建了臨時環(huán)境稽穆,是時候添加 .xcconfig 文件了冠王。


Creating Configuration Settings Files

使用 Build Settings選項卡修改設置有一些缺點。 搜索具有不同范圍的長列表非常耗時舌镶,尤其是當您有多個targets柱彻、build configuration和設置需要管理時豪娜。 .xcconfig 文件是簡化此過程的替代方法。

在項目導航器中選擇 NinjaCounter 組哟楷。 創(chuàng)建一個新group瘤载。 命名組為Config Files。 這是您放置配置文件的地方卖擅。

單擊File ? New ? File…鸣奔。

在文件模板列表中選擇Configuration Settings File

將文件命名為 Debug.xcconfig磨镶。 對于此應用程序溃蔫,您需要為每個配置創(chuàng)建一個 .xcconfig 文件。 創(chuàng)建 Staging.xcconfigRelease.xcconfig琳猫。

注意:不要將 .xcconfig 文件添加到target memberships伟叛。 配置設置文件旨在成為開發(fā)依賴項(development dependencies)。 它們不應包含在app archive中的資源中脐嫂。

接下來统刮,您將在 Xcode 中設置配置文件。


Working With Configuration Settings Files

要使用配置文件账千,您需要在 Xcode 中設置它們侥蒙。 在此之前,添加app display name的設置匀奏。

打開 Debug.xcconfig鞭衩。 添加下面的設置并保存。

APP_NAME = Ninja Counter

.xcconfig 文件中的設置使用以下語法:SETTING_NAME = VALUE娃善。

注意:即使字符串值包含空格论衍,也不要像 Ninja Counter 那樣用引號將字符串值括起來。 例外情況是聚磺,包含空格的字符串在string list中時坯台,字符串列表是以空格分隔的字符串值列表。

打開項目編輯器并選擇 NinjaCounter 項目瘫寝。 單擊Info選項卡蜒蕾。

Configurations部分是您設置配置文件的地方。

如您所見焕阿,您可以在project level以及每個target level為每個環(huán)境使用配置文件咪啡。

Based on Configuration File下,單擊配置文件選項暮屡。

Xcode 會顯示您創(chuàng)建的 .xcconfig 文件列表瑟匆。 將每個構(gòu)建配置對應的配置文件設置為app and widget targets,如下圖:

  • Debug
    • NinjaCounter: Debug
    • WidgetExtension: Debug
  • Staging
    • NinjaCounter: Staging
    • WidgetExtension: Staging
  • Release
    • NinjaCounter: Release
    • WidgetExtension: Release

此時,您已經(jīng)為每個環(huán)境創(chuàng)建了一個配置文件愁溜。 做得好! 接下來外厂,您將為每個環(huán)境自定義設置冕象。

1. Creating a User-Defined Setting to Change the Bundle Display Name

作為開發(fā)人員,您可以在應用的所有階段使用和使用您的應用汁蝶。 當您在不同版本之間切換時渐扮,了解您當前安裝的是哪個版本可能會令人困惑。 因此掖棉,使用不同的display names很有用墓律。

打開 Debug.xcconfig。 將 APP_NAME的值更改為 Ninja CounterDev幔亥。 這是您在安裝調(diào)試版本時將看到的應用程序顯示名稱耻讽。

現(xiàn)在,您一目了然就知道這是您正在使用絕密和下一代功能進行的開發(fā)版本帕棉!

接下來针肥,您需要更改其他配置的名稱。 打開 Staging.xcconfig 并添加以下行:

APP_NAME = Ninja CounterQA

最后香伴,打開 Release.xcconfig 并使用生產(chǎn)display name更新設置:

APP_NAME = Ninja Counter

接下來慰枕,在Project navigator中選擇項目本身。 選擇 NinjaCounter 應用程序target即纲。

打開Build Settings選項卡具帮。 滾動到列表末尾。

現(xiàn)在低斋,您可以看到用戶定義的構(gòu)建設置 APP_NAME 和顯示配置文件級別值的新設置范圍蜂厅。 如果您在這里看到您在配置文件中設置的值,那么您就走對了拔稳!

更改應用程序display name的最后一步是將 Bundle display name設置為引用您的用戶定義設置葛峻。

打開 NinjaCounterInfo.plist。 添加Bundle display name屬性巴比。 將該屬性的值設置為 $(APP_NAME)术奖。

或者,您也可以從Project EditorInfo選項卡中添加它轻绞。

確保將 NinjaCounter 設置為active scheme采记。

構(gòu)建并運行。 按 Shift-Command-H 進入主屏幕政勃。

現(xiàn)在唧龄,您可以看到您的開發(fā)構(gòu)建應用程序名稱。

是時候在 Staging 環(huán)境中測試應用程序了奸远。 按住 Option 鍵并單擊 Xcode 任務欄中的運行按鈕既棺。

接下來讽挟,選擇 Run 操作,然后選擇 Info 選項卡丸冕,然后單擊 Build Configuration 下拉菜單耽梅。 您的新staging configuration在列表中。 選擇Staging作為構(gòu)建配置胖烛。

單擊Run眼姐,等待應用程序啟動,然后返回 iOS 主屏幕佩番。

應用程序顯示名稱現(xiàn)在是 NinjaCounterQA众旗,可立即顯示您正在使用的構(gòu)建版本。

接下來,您將創(chuàng)建一個基本配置文件以避免冗余值。

2. Retaining Values With Inheritance

在您的配置文件中臭觉,您將不同構(gòu)建的 APP_NAME 設置為 Ninja CounterDev哼御、Ninja CounterQA 和 Ninja Counterrelease build 名稱 NinjaCounter 是基本值,您可以在每個名稱中重復該值。

project level設置常規(guī)構(gòu)建設置是最佳實踐。 然后哗咆,在不同的配置中重復使用這些設置以避免冗余。 在這種情況下益眉,您將在每個構(gòu)建配置中更改 APP_NAME 以從基本值繼承晌柬。

右鍵單擊Config files group。 選擇New file…郭脂。 創(chuàng)建一個名為 Base.xcconfig 的新配置文件并添加以下行:

APP_NAME = Ninja Counter

接下來年碘,替換其他配置文件的內(nèi)容如下。

Debug.xcconfig:

#include "Base.xcconfig"

APP_NAME = $(inherited)Dev

Staging.xcconfig:

#include "Base.xcconfig"

APP_NAME = $(inherited)QA

Release.xcconfig:

#include "Base.xcconfig"

在這里展鸡,您更改了三個配置文件以從 Base.xcconfig 繼承和重用基本設置屿衅。 您通過使用 $(inherited)并附加特定于每個構(gòu)建的名稱部分來完成此操作。

注意: $(inherited)值是從包含的文件中引用的(如果有)莹弊,并遵循前面提到的優(yōu)先級涤久。 同樣,如果您在配置文件中繼承系統(tǒng)構(gòu)建設置忍弛,則將根據(jù)優(yōu)先級設置解析值响迂。

最后,在 Staging 中構(gòu)建并運行應用程序细疚。

應用名稱顯示正確蔗彤。 請注意,您不需要將 APP_NAME 定義添加到 Release.xcconfig。 那是因為設置會回退到繼承的值然遏。

要查看設置在 Xcode 中的顯示方式贫途,請打開Project Editor。 選擇 NinjaCounter target啦鸣,然后選擇Build Settings潮饱。 滾動到User-defined部分。

盡管在應用程序運行時顯示正確诫给,但解析的值看起來并不正確。 這是因為 Base.xcconfig 未在Project EditorConfigurations部分中設置啦扬。 但是中狂,繼承在運行時按預期解析。

要解決此問題扑毡,請在項目編輯器中選擇項目胃榕。 在Configurations下,在所有三個配置的項目級別設置 Base.xcconfig瞄摊。

現(xiàn)在勋又,返回app targetBuild Settings

這些值現(xiàn)在在 Xcode 中正確顯示换帜。 請注意楔壤,新范圍顯示了項目級配置文件。

接下來惯驼,您將添加更多自定義設置蹲嚣。

3. Referencing Values of Other Settings

現(xiàn)在您的環(huán)境已準備就緒,是時候添加更多設置了祟牲。 將以下內(nèi)容添加到 Base.xcconfig隙畜。 請務必替換您的bundle identifier

BASE_BUNDLE_IDENTIFIER = <your bundle identifier>

PRODUCT_BUNDLE_IDENTIFIER = $(BASE_BUNDLE_IDENTIFIER)

BASE_BUNDLE_IDENTIFIER 是包含項目基本bundle identifier的用戶定義設置,而 PRODUCT_BUNDLE_IDENTIFIER 是指定bundle identifierXcode 構(gòu)建設置说贝。

在這里议惰,您引用了 BASE_BUNDLE_IDENTIFIER 的值。 參考語法為:$(OTHER_BUILD_SETTING_NAME)乡恕。

注意:當您從 Info.plist.entitlements 文件中引用構(gòu)建設置時言询,您使用相同的引用語法。

現(xiàn)在几颜,如果您要更改 Base.xcconfigBASE_BUNDLE_IDENTIFIER 的值倍试,您將看不到構(gòu)建設置中反映的更改。 那是因為bundle identifier目前在target’s settings中是硬編碼的蛋哭。 要解決此問題县习,請返回到Project Editor并選擇NinjaCounter target。 在搜索字段中,輸入 bundle 以縮小設置顯示的數(shù)量躁愿。 雙擊target build setting并將其值更改為:

$(inherited)

之前叛本,您將 UserDefaultsHelper.swift 中的代碼更改為使用app group identifier作為 UserDefaults 套件名稱,如下所示彤钟。

UserDefaults(suiteName: "group.<your bundle identifier>")

為了避免像套件名稱這樣的硬編碼值来候,請在 Base.xcconfig 中的 PRODUCT_BUNDLE_IDENTIFIER 下添加以下設置:

USER_DEFAULTS_SUITE_NAME = group.$(BASE_BUNDLE_IDENTIFIER)

由于 NinjaCounter 中的app group identifier取決于bundle identifier,因此您創(chuàng)建了 USER_DEFAULTS_SUITE_NAME逸雹。 它內(nèi)聯(lián)引用 BASE_BUNDLE_IDENTIFIER 并附加group.前綴营搅。 稍后,您將更新您的代碼以使用此新設置梆砸,但首先您必須更新應用程序以使用該設置转质。 在項目導航器中,您將找到兩個 .entitlements 文件帖世。 打開 WidgetExtension.entitlements 并單擊disclosure arrow以打開設置休蟹。 將 Item 0 的值更改為:

$(USER_DEFAULTS_SUITE_NAME)

接下來,打開 NinjaCounter.entitlements 并執(zhí)行相同的操作日矫。

您通過引用其他設置的值來確保依賴于其他設置的構(gòu)建設置的一致性赂弓。 接下來,您將在代碼中使用該設置并刪除硬編碼的設置哪轿。

4. Accessing Settings From Code

要從代碼訪問構(gòu)建設置盈魁,您首先需要在 Info.plist 中添加一個引用屬性。 打開 NinjaCounterInfo.plist并添加一個名為的自定義屬性:

USER_DEFAULTS_SUITE_NAME

使用下面的值:

$(USER_DEFAULTS_SUITE_NAME)

widgetInfo.plist 執(zhí)行相同操作缔逛,因為widget也需要訪問設置备埃。

接下來,在 NinjaCounter組中創(chuàng)建一個新的 Swift 文件并將其命名為 Config.swift褐奴。 打開文件并添加以下代碼:

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
  }
}

stringValue(forKey:) 是一種輔助方法按脚,可簡化從 Info.plist 檢索值的過程。 它調(diào)用 Bundleobject(forInfoDictionaryKey:)來獲取字符串值敦冬。

注意:您可以從屬性列表中存儲和獲取其他數(shù)據(jù)類型辅搬,例如布爾值和數(shù)組。 為簡單起見脖旱,由于 NinjaCounter 只需要字符串值堪遂,因此此輔助方法僅適用于字符串。

然后萌庆,在文件檢查器中溶褪,除了 NinjaCounter 之外,還選擇 WidgetExtension 作為target践险。

打開 UserDefaultsHelper.swift 并再次將defaults聲明替換為:

static private let defaults = UserDefaults(
  suiteName: Config.stringValue(forKey: "USER_DEFAULTS_SUITE_NAME"))
  ?? .standard

在這里猿妈,您更改了 UserDefaultsHelper 的代碼以從構(gòu)建設置中獲取套件名稱吹菱。 您使用了 Config 的方法 stringValue(forKey:) 來獲取值。

接下來彭则,您將添加條件設置鳍刷。

5. Adding Conditions

您可以添加條件來構(gòu)建設置以針對特定的 SDK, architecturebuild configurationtarget。 在添加不特定于targetproject范圍設置時俯抖,這尤其有用输瓜。

Base.xcconfig 中,添加以下行:

ONLY_ACTIVE_ARCH[config=Debug][sdk=*][arch=*] = YES

在這里芬萍,當應用程序在Debug configuration中構(gòu)建時尤揣,您將 ONLY_ACTIVE_ARCH 設置為 YES。 因此柬祠,它通過僅構(gòu)建active architecture來加快構(gòu)建時間芹缔。

條件設置遵循以下語法:

BUILD_SETTING_NAME[條件=值] = VALUE

將條件值設置為星號意味著任何值。 您在上面添加的設置適用于任何 sdk 和任何architecture瓶盛,但僅適用于Debug configuration

在下一部分中示罗,您將自定義應用程序在不同環(huán)境中的行為惩猫。


Creating Record Stores for Each Environment

現(xiàn)在您的環(huán)境已準備就緒,您將孵化器的記錄存儲在不同的 UserDefaults 鍵中 —— 每個環(huán)境一個蚜点。 由于應用在本地存儲數(shù)據(jù)轧房,這里的 UserDefaults 是應用的“back end”

是時候在環(huán)境的配置文件中添加 UserDefaults 鍵了绍绘。

Debug.xcconfig 中奶镶,添加:

USER_DEFAULTS_RECORDS_KEY = HatchlingsRecords-Debug

Staging.xcconfig 中,添加:

USER_DEFAULTS_RECORDS_KEY = HatchlingsRecords-Staging

Release.xcconfig 中陪拘,添加:

USER_DEFAULTS_RECORDS_KEY = HatchlingsRecords

密鑰名稱在每個環(huán)境中都會發(fā)生變化厂镇。

接下來,將以下屬性添加到 NinjaCounter 和擴展的 Info.plist 中左刽。

Key

USER_DEFAULTS_RECORDS_KEY

Value

$(USER_DEFAULTS_RECORDS_KEY)

之后捺信,打開 UserDefaultsHelper.swift 并將recordsKey的聲明替換為:

static private let recordsKey = Config
  .stringValue(forKey: "USER_DEFAULTS_RECORDS_KEY")

正如您從構(gòu)建設置中獲得 UserDefaults 套件名稱一樣,在上面的更改中欠痴,您使用 stringValue(forKey:)將硬編碼的 UserDefaults 鍵替換為相應的構(gòu)建設置值迄靠。

最后,您已準備好測試您的更改喇辽! 將active schemeBuild Configuration更改為Debug掌挚。

構(gòu)建并運行。 添加Donatello記錄菩咨。

接下來吠式,將Build Configuration更改為Release陡厘。 構(gòu)建并運行。

您看不到 Donatello 的記錄奇徒,因為您將其存儲在 Debug 存儲區(qū)中雏亚。 將Build Configuration更改回Debug。 構(gòu)建并運行摩钙。

您在使用debug build configuration運行時存儲的記錄就在那里罢低。 現(xiàn)在,您知道您的環(huán)境按預期工作胖笛。

這是否讓您想起了不同的方法网持? 看看下面的代碼。

#if DEBUG
let recordsKey = "HatchlingsRecords-Debug"
#elseif STAGING
let recordsKey = "HatchlingsRecords-Staging"
#else
let recordsKey = "HatchlingsRecords"
#endif

條件編譯是一種流行的做法长踊。 但是功舀,使用它來管理跨環(huán)境的常量有一個缺點,即您將可配置的常量與代碼混合在一起身弊。 使用build settings來存儲這些值并在代碼中使用它們是一個不錯的選擇辟汰。

那很簡單! 在配置文件中設置設置不僅可以簡化構(gòu)建設置的管理阱佛,還可以讓您從 Xcode 外部化設置帖汞。 這使它們具有可移植性,并使跟蹤源代碼管理中的更改更加方便凑术。

在下一部分中翩蘸,您將為每個target創(chuàng)建配置文件。


Using Configuration Files for Each Target

該應用程序現(xiàn)在在所有三種環(huán)境中都可以正常運行淮逊。 但是催首,如果您需要為 WidgetExtention 創(chuàng)建或外部化target-specific的構(gòu)建設置怎么辦? 接下來泄鹏,您將看到如何為widget target創(chuàng)建配置文件郎任。

Config files group中,創(chuàng)建以下配置文件:

  • WidgetBase.xcconfig:
#include "Base.xcconfig"

PRODUCT_BUNDLE_IDENTIFIER = $(BASE_BUNDLE_IDENTIFIER).widget
  • WidgetDebug.xcconfig
#include "Debug.xcconfig"
#include "WidgetBase.xcconfig"
  • WidgetStaging.xcconfig
#include "Staging.xcconfig"
#include "WidgetBase.xcconfig"
  • WidgetRelease.xcconfig
#include "Release.xcconfig"
#include "WidgetBase.xcconfig"

在這里命满,您通過將 BASE_BUNDLE_IDENTIFIER 附加到您的基本設置來設置widget PRODUCT_BUNDLE_IDENTIFIER涝滴。

接下來,在Project Editor中為 WidgetExtension target將文件設置為各自的環(huán)境胶台,如下所示歼疮。

  • Debug
    • Project: Base
    • NinjaCounter: Debug
    • WidgetExtension: WidgetDebug
  • Staging
    • Project: Base
    • NinjaCounter: Staging
    • WidgetExtension: WidgetStaging
  • Release
    • Project: Base
    • NinjaCounter: Release
    • WidgetExtension: WidgetRelease

注意:您不需要設置 WidgetBase.xcconfig,因為其他文件都包含它诈唬。

最后韩脏,返回到 Project Editor 并將 WidgetExtension targetProduct Bundle Extension 設置更改為:

$(inherited)

之后,將active scheme更改為 WidgetExtension铸磅。 確保構(gòu)建配置為Debug赡矢。 構(gòu)建并運行杭朱。

widget現(xiàn)在顯示您為 Donatello 添加的最新記錄。 盡管 WidgetDebug.xcconfig 不包含任何設置吹散,但它包含來自 WidgetBase.xcconfigDebug.xcconfig 的設置弧械。 這就是當您為widget設置 Debug.xcconfig 時它起作用的原因。


Differentiating the App Icon for Non-Release Builds

一些利益相關(guān)者空民,如測試人員和 QA 工程師刃唐,使用多個版本的應用程序。 例如界轩,他們可能會使用 App Store 版本和開發(fā)人員或 TestFlight提供的 Staging 版本画饥。 為了讓您同事的生活更輕松,您的下一步將是更改應用程序圖標浊猾,以區(qū)分 DebugStaging 版本與 Release 版本抖甘。

在項目中,您將在應用程序的 Assets.xcassets 中找到另一個名為 AppIcon-NonProd 的應用程序圖標集葫慎。

設置資產(chǎn)目錄應用圖標集的名稱衔彻,需要修改配置文件中的ASSETCATALOG_COMPILER_APPICON_NAME

Debug.xcconfigStaging.xcconfig 中偷办,添加:

ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon-NonProd

Release.xcconfig中米奸,添加:

ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon

注意:正如您在 Project EditorBuild Settings 選項卡和 Info.plist 中看到的,有許多構(gòu)建設置爽篷。 你不必記住每個的名字。 相反慢睡,請使用 Apple 文檔中的build settings reference逐工。

active scheme設置為 NinjaCounter。 將Build Configuration設置為Debug漂辐。 構(gòu)建并運行泪喊。 進入主屏幕。

圖標沒有改變髓涯,因為Target Build Settings具有更高的優(yōu)先級袒啼。 要解決此問題,請從項目編輯器轉(zhuǎn)到 NinjaCounter targetBuild Settings 纬纪,然后找到Asset Catalog App Icon Set Name蚓再。

在配置文件的范圍內(nèi),您可以看到添加到配置文件中的值包各。 但是摘仅,該設置解析為target scope內(nèi)的值。

要解決此問題问畅,請將app target范圍的父值更改為 $(inherited)娃属。

解析的值現(xiàn)在與配置文件匹配六荒。

構(gòu)建并運行。 進入主屏幕矾端。

該應用程序現(xiàn)在顯示 AppIcon-NonProd 應用程序圖標集中的圖標掏击。

注意:在widget的資產(chǎn)目錄中,有一個名為 AppIcon-NonProd 的空應用圖標集秩铆。雖然它沒有被使用砚亭,但它解決了編譯時錯誤,Xcode 會警告widget的資產(chǎn)目錄中不存在 AppIcon-NonProd豺旬。這是因為widget targetapp target繼承 ASSETCATALOG_COMPILER_APPICON_NAME钠惩,Xcode將在編譯時檢查該值。

在本教程中族阅,您使用 .xcconfig 文件來外部化構(gòu)建設置篓跛。你涵蓋:

  • 跨不同build configurations管理設置。
  • 針對不同環(huán)境和targets使用配置文件的多種方法坦刀。
  • 從代碼訪問構(gòu)建設置愧沟。

有關(guān)build configuration and app distribution best practices的更多信息,請查看我們iOS App Distribution & Best Practices一書鲤遥。

以下是 Apple 文檔中的一些更有用的資源:

后記

本篇主要講述了使用Build Configurations.xcconfig 構(gòu)建你的App沐寺,感興趣的給個贊或者關(guān)注~~~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市盖奈,隨后出現(xiàn)的幾起案子混坞,更是在濱河造成了極大的恐慌,老刑警劉巖钢坦,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件究孕,死亡現(xiàn)場離奇詭異,居然都是意外死亡爹凹,警方通過查閱死者的電腦和手機厨诸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來禾酱,“玉大人微酬,你說我怎么就攤上這事〔眨” “怎么了颗管?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長滓走。 經(jīng)常有香客問我忙上,道長,這世上最難降的妖魔是什么闲坎? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任疫粥,我火速辦了婚禮茬斧,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘梗逮。我一直安慰自己项秉,他們只是感情好,可當我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布慷彤。 她就那樣靜靜地躺著娄蔼,像睡著了一般。 火紅的嫁衣襯著肌膚如雪底哗。 梳的紋絲不亂的頭發(fā)上岁诉,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天,我揣著相機與錄音跋选,去河邊找鬼涕癣。 笑死,一個胖子當著我的面吹牛前标,可吹牛的內(nèi)容都是我干的坠韩。 我是一名探鬼主播,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼炼列,長吁一口氣:“原來是場噩夢啊……” “哼只搁!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起俭尖,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤氢惋,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后稽犁,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體明肮,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年缭付,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片循未。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡陷猫,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出的妖,到底是詐尸還是另有隱情绣檬,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布嫂粟,位于F島的核電站娇未,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏星虹。R本人自食惡果不足惜零抬,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一镊讼、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧平夜,春花似錦蝶棋、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至段直,卻和暖如春吃溅,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背鸯檬。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工决侈, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人京闰。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓颜及,卻偏偏與公主長得像,于是被迫代替她去往敵國和親蹂楣。 傳聞我的和親對象是個殘疾皇子俏站,可洞房花燭夜當晚...
    茶點故事閱讀 45,037評論 2 355

推薦閱讀更多精彩內(nèi)容