讀古今文學網 > iOS編程基礎:Swift、Xcode和Cocoa入門指南 > 6.4 目標 >

6.4 目標

所謂目標就是規則與設置的集合,這些規則與設置用於指定如何構建產品。在構建時,你所構建的實際上是個目標(可能還會有多個目標)。

在項目導航器頂部選中Empty Window項目,你會在編輯器左側看到兩部分內容(如圖6-7所示):項目本身以及目標列表。Empty Window項目有一個目標:應用目標,叫作Empty Window(就像項目本身一樣)。應用目標是用於構建和運行應用的目標。其設置會告訴Xcode如何構建應用;其產品就是應用本身。

在某些情況下,你可能會向項目添加更多的目標:

·你想要執行單元測試或界面測試;為了做到這一點,你會添加一個目標。(第9章將會對測試進行更多的介紹。)

·你想要編寫一個框架並作為自己的iOS應用的一部分;借助自定義框架,你可以將共同代碼重構到一處,可以通過命名空間來重構其私有性細節信息。自定義框架是需要構建的,因此它也是個目標。(本章後面將會對框架進行更多的介紹。)

·你想要編寫應用擴展,比如,今日擴展(出現在通知中心的內容),或圖片編輯擴展(出現在照片應用上的圖片編輯界面)。它們也都是目標。

項目名與目標列表可以通過兩種方式呈現(如圖6-7所示):一種是作為列顯示在編輯器左側;如果將該列收起以節省空間,那麼它還可以作為彈出菜單顯示在編輯器左上角。如果在列或彈出菜單中選中了項目,那就可以編輯項目;如果選中了某個目標,那就可以編輯該目標。我會在後面的表述中使用這種說法。

圖6-7:展示項目與目標的兩種方式

6.4.1 構建階段

編輯應用目標並單擊編輯器頂部的Build Phases(如圖6-8所示),這些是應用的構建階段。構建階段既描述了目標的構建方式,也包含了一套指令,指示Xcode該如何構建目標;如果修改了構建階段,那麼構建過程也會隨之修改。單擊每個構建階段可以查看該構建階段所應用的目標中的文件列表。

有兩個構建階段是有內容的。這些構建階段的含義也是一目瞭然的:

圖6-8:應用目標的構建階段

編譯源

會編譯某些文件(代碼),生成的編譯代碼會被複製到應用中。

該構建階段通常會作用於所有目標的.swift文件上;它們是構成目標的代碼文件。顯然,它會包含ViewController.swift與AppDelegate.swift。如果向項目添加了新的Swift文件(通常是為了聲明另一個類),那麼你應該將其指定為應用目標的一部分,它會自動添加到編譯源構建階段中。

複製包資源

某些文件會被複製到應用中,這樣在應用運行時,代碼或系統就能找到它們了。

該構建階段目前會作用於資源目錄上;添加到資源目錄中的任何資源都會被複製到應用中作為目錄的一部分。它還會列出啟動storyboard文件LaunchScreen.storyboard與應用的界面storyboard文件Main.storyboard文件。

複製並不意味著進行完全的複製。某些類型的文件在複製到應用包中時會通過幾種方式被特殊對待。比如,複製資源目錄意味著目錄中的圖標會被寫到應用包的頂層,資源目錄本身會被轉換為.car文件;複製.storyboard文件意味著它會被轉換為.storyboardc文件,該文件本身是個包含nib文件的包。

你可以手工修改這些列表,有時也需要這麼做。比如,如果項目中的某些文件(如聲音文件)不在複製包資源中,但你又想在構建過程中將其複製到應用中,那麼你可以將其從項目導航器中拖曳到複製包資源列表中,或(更加簡單的方式)單擊複製包資源列表下方的「+」按鈕來彈出一個對話框,該對話框會列出項目中的所有內容。相反,如果項目中的某些文件位於複製包資源中,但你又不想將其複製到應用中,那麼你可以從列表中將其刪除;這麼做並不會將其從項目、項目導航器或Finder中刪除,而只會從複製到應用中的條目列表中刪除。

有時需要修改Link Binary With Libraries構建階段,某些庫(通常是框架)會鏈接到編譯後的代碼上(編譯之後叫作庫),這會告訴代碼,當應用運行時,設備上需要這些庫。Empty Window項目會鏈接到一些框架,不過它並未使用該構建階段;相反,它將框架導入為模塊,框架就會自動鏈接。不過,在某些情況下,你需要顯式將二進制文件鏈接到額外的框架上;本章後面將會對此進行介紹。

一個實用的技巧是添加Run Script構建階段,它會在構建過程中運行一個自定義shell腳本。要想做到這一點,請選擇Editor→Add Build Phase→Add Run Script Build Phase。打開新添加的Run Script構建階段可以編輯自定義shell腳本。最簡單的一個shell腳本如下所示:


echo \"Running the Run Script build phase\"
  

勾上「Show environment variables in build log」復選框會在Run Script構建階段的構建報告中列出構建過程中的環境變量及其值。單憑這一點我們就應該加上Run Script構建階段;通過查看環境變量可以瞭解到關於構建過程如何進行的很多信息。

6.4.2 構建設置

構建階段只是目標瞭解如何構建項目的一個方面。另外一個方面就是構建設置。要想查看構建設置,請編輯目標並在編輯器頂部單擊構建設置(如圖6-9所示)。你會看到一個長長的設置列表,其中大部分設置都不用修改。Xcode會檢查該列表以便瞭解在構建過程的各個階段應該做什麼。項目之所以會按照期望的方式編譯和構建,完全是因為構建設置在起作用。

圖6-9:目標構建設置

你可以通過單擊Basic或All來顯示不同的構建設置。設置會被組合為類別,你可以關閉或打開每個類別標題以節省空間。如果瞭解想要查看的某個設置,如它的名字,那麼你就可以通過右上角的搜索框來過濾顯示的設置。

你可以通過單擊Combined或Levels來決定構建設置的顯示方式;在圖6-9中,我單擊了Levels,目的是介紹何謂Levels。不僅目標包含了構建設置的值,項目也包含了相同構建設置的值;此外,Xcode擁有一些內建的默認構建設置值。Levels會同時顯示出這些層級,這樣你就能清楚每個構建設置的實際值的來源了。

要想理解這張圖,請從右向左看。比如,Build Active Architecture Only設置的Debug配置(最右側)默認為No。不過,項目中將其設為了Yes(右側第2列)。目標並未修改該設置(右邊第3列),因此結果就是設置被解析為了Yes(右側第4列)。

如果想要改變其值,你可以現在就改。你可以在項目層次或目標層次上修改其值。我並不建議你這麼做;事實上,你很少會直接操縱構建設置,因為通常情況下,默認值就可以了。然而,你還是可以修改構建設置值的,就在這裡修改。要想瞭解各種構建設置的詳細信息,請參考Apple的文檔,特別是Xcode構建設置參考文檔。此外,你還可以選擇某個構建設置,然後在輔助窗格中顯示快速幫助以瞭解更多信息。要想瞭解各種構建設置的詳細信息,請參考Apple的文檔,特別是Xcode構建設置參考文檔。

6.4.3 配置

實際上,構建設置值會有多個列表,但在執行構建時只有一個列表會發揮作用。每個列表都叫作一個配置。我們需要多個配置,因為你會在不同的時間針對不同的目的採用不同的構建方式,這樣就需要某些構建設置在不同的情況下接受不同的值。

默認情況下,有如下兩個配置:

調試

該配置用於開發過程,也就是編寫和運行應用的時候。

發佈

該配置用於後期的測試,也就是在設備上檢查性能,以及將應用打包提交到App Store的時候。

之所以需要配置完全是因為項目的需要。要想查看項目中的配置,請編輯項目並單擊編輯器頂部的Info(如圖6-10所示)。注意到這些配置僅僅是名字而已。你可以添加更多的配置,這只不過是向名字列表中添加名字而已。配置的重要性只在這些名字與構建設置值關聯起來時才會顯現出來。配置會在項目與目標級別上影響構建設置值。

圖6-10:配置

比如,回到目標構建設置(如圖6-9所示)並在搜索框中輸入「Optim」。你會看到Optimization Level構建設置(如圖6-11所示)。Optimization Level的調試配置值是None:在開發應用時,你會使用調試配置來構建,這樣代碼就會以一種直觀的方式一行一行地進行編譯。Optimization Level的發佈配置值是Fast;當應用準備發佈時,你會使用發佈配置進行構建,這樣生成二進制文件時就會針對速度進行優化,非常適合於用戶在設備上運行應用,但卻不適合開發,因為調試器中的斷點與步進將無法使用。

圖6-11:配置是如何影響構建設置的

對於發佈配置Optimization Level設置,更好的選擇是Fast,Whole Module Optimization。這樣,Swift編譯器就會立刻檢查所有代碼文件。編譯時間可能會長一些,不過優化結果會更好;比如,編譯器可能會推斷出某些類成員無須動態分派,這會加快代碼的運行速度。

6.4.4 方案與目標

到目前為止,我還沒有介紹在某次構建過程中,Xcode是如何知道配置的。這是由方案來決定的。

方案會根據構建目的將一個或多個目標與構建配置組合起來。在默認情況下,新的項目都自帶一個方案,並以項目名命名。這樣,Empty Window項目的方案就叫作Empty Window。要想查看它,請選擇Product→Scheme→Edit Scheme,這會打開模式編輯器對話框(如圖6-12所示)。

圖6-12:方案編輯器

方案編輯器左邊列出的是你可以從Product菜單中執行的各種動作。單擊某個動作可以在該方案中查看到其相應的設置。

第1個動作構建動作與其他動作不同,因為其他動作都會用到構建動作,其他動作都會隱式涉及構建。構建動作只是在其他動作執行時用來決定構建哪些目標。對於我們的項目來說,它意味著無論執行的動作是什麼,應用目標總是會被構建。

第2個動作(運行動作)決定了構建和運行時所需的設置。構建配置彈出菜單(在信息窗格中)被設為了調試。這說明了當前的構建配置的來源:現在,在構建和運行時(Product→Run,或單擊工具欄中的Run按鈕),你使用的是調試構建配置和與其相對應的構建設置值,因為你使用的是該方案,這正是構建與運行時該方案所要做的事情。

你可以編輯已有的方案,不過一般來說不需要這麼做。另一種可能是創建新的方案。一種方式是從項目窗口工具欄的Scheme彈出菜單中選擇Manage Schemes(如圖6-13所示)。

方案彈出菜單是經常會用到的一個功能。所有方案都會在此列出,因此在構建和運行前可以輕鬆在各個方案間切換。目標(Destination)會以層次方式附加到每個方案上。目標就是運行應用的機器。比如,你可能會在物理設備或模擬器中運行應用。如果是模擬器,那就需要指定要模擬的特定類型的設備。可以在方案彈出菜單中選擇目標。

圖6-13:方案彈出菜單

目標與方案之間並沒有什麼關係。方案彈出菜單中會有目標主要是起到方便的作用,這樣你就可以使用彈出菜單一次性地來選擇方案或目標了,也可以同時選擇這兩者。要想在不改變方案的情況下切換目標,請在方案彈出菜單中單擊目標名。要想切換方案,或確定目標(如圖6-13所示),請在方案彈出菜單中單擊方案名。

每個模擬設備都有一個安裝到設備上的系統版本。目前,我們所模擬的設備都運行著iOS 9.0;這樣就沒有差別了,系統版本就沒有顯示出來。不過,可以在Xcode的首選項窗格中下載其他SDK(系統)。如果下載了並且應用可以運行在多個系統版本上,你還會在Scheme彈出菜單中看到系統版本成為目標名的一部分。比如,如果安裝了iOS 8.4 SDK,同時項目的部署目標(參見第9章)是8.0,那麼項目窗口工具欄中的方案彈出菜單就會在目標名後面顯示「iOS 9.0」或是「iOS 8.4」。

如果下載了額外的SDK,並且應用配置為在多個系統上運行,要是看不到使用了這些系統的任何模擬設備,那麼請選擇Window→Device來彈出Devices窗口。這是管理模擬設備的地方。可以在這裡創建、刪除和重命名模擬設備,還可以指定某個模擬設備是否會作為目標出現在方案彈出菜單中。