到目前為止,你依照步驟一步一步建立了Hello World App。整章讀完後想必心中會出現了幾個疑問:
- Storyboard中的視圖控制器是如何與ViewController.swift檔內的ViewController類別(class)建立連結。
- showMessage()方法中的那段程式碼是什麼意思呢?它要如何告知iOS顯示一個HelloWorld訊息?
- @IBAction這個關鍵字是做什麼用的?
- 「Hello World」按鈕背後藏了什麼?按鈕是如何偵測到按下事件,並進而觸發showMessage()方法?
- 「Run」按鈕在Xcode中是如何運作的?所謂編譯一個App是什麼意思?
之前,我想要你專注在探索與熟悉Xcode的開發環境,所以一開始沒有對以上的問題多作說明,然而了解程式碼背後運作的細節與掌握iOS程式的基礎觀念是有其必要性的。有些技術性的觀念,或許會有點難懂,尤其是針對之前毫無程式開發背景的初學者而言更是。但是,其實不必擔心,這只是開始而已。當你照著後續的章節繼續學習,寫了更多的程式碼之後,你便會更了解iOS程式語言。你現在最需要做的一件事就是盡心學習。
好的,從生活中舉個真實的例子來說明。
例如:電視遙控器,可以很方便地以無線方式遠端調整聲音。當想要更換頻道,你只要簡單地按下頻道號碼即可。如果想要提高音量,只要按下音量「+」按鈕即可。
請問你是否知道在按下音量按鈕或者頻道按鈕之後,背後發生了什麼事情嗎?我相信大部分的人不知道也不明白遙控器與電視之間是如何進行無線溝通的。你可能會想像就是遙控器送出某個訊息給電視,然後進一步啟動音量調整或者頻道切換。
在這個案例中,跟你互動的按鈕一般通常定位為介面(interface),而隱藏在按鈕背後的細節就是實作(implementation)。介面與實作間的溝通是透過訊息。
這樣的觀念也應用到iOS程式世界。很明顯地,在Storyboard上所佈局的使用者介面,就是操作介面,而程式碼的部分就是實作。使用者介面元件(例如:按鈕)透過某種訊息和程式碼溝通。
當回到Hello World專案,你在視圖中加入的按鈕就是所謂的介面。ViewController類別的showMessage()方法就是實作。當某人按下按鈕,它會傳送一個showMessage訊息到ViewController,而觸發showMessage()方法。
剛剛述及的部分是物件導向程式(Objective Oriented Programming)中一個很重要的觀念,稱為「封裝(Encapsulation)」。showMessage()方法的實作是隱藏於外面的世界(也就是介面)背後,Hello World按鈕並不清楚showMessage()方法是如何運作的。我們所知道的是,這個按鈕只負責傳遞訊息而已,而showMessage() 方法接手處理剩下的工作,也就是呈現「Hello World」訊息在畫面上。
觸控背後
現在你已經了解了UI中的按鈕經由某種訊息和程式碼進行溝通。更精確地說,當使用者點選「Hello World」按鈕時,實際發生了什麼事情呢?「Hello World」按鈕是如何呼叫showMessage()方法呢?
你是否還記得你已經將介面建構器中的「Hello World」按鈕與showMessage事件建立連結?請再次打開Main.storyboard,並且選擇「Hello World」按鈕,在工具區點選連結檢閱器(Connection Inspector)。在Sent Events區塊,你可以找到一串可以取得的事件與相對應要呼叫的方法。如下圖所示,「Touch Up Inside」事件連結到showMessage()方法。
在iOS中,App是以事件驅動的程式為基礎。不論是系統物件或UI物件,它監聽某個觸控事件來決定App的運作流程。以一個UI元件(例如:按鈕)來說,它可能監聽到特定的觸控事件。當這事件被觸發,這個物件就會呼叫與這個事件關聯的預設方法。
Hello World App中,當使用者的手指從按鈕內提起後,「Touch Up Inside」事件被觸發。結果,它呼叫了showMessage() 方法來顯示「Hello World」訊息。我們使用「Touch Up Inside」事件取代「Touch Down」,是因為我們要避免偶發狀況或誤觸,下圖整理了整個事件的流程以及我所談及的部分。
深入了解showMessage方法
你應該對iOS程式有了進一步的認識,不過在showMessage()方法內的程式碼區塊是什麼呢?
首先要知道的是,什麼是方法?如同之前所提到的,App中的程式碼多數是以某種方式在處理某種物件。每一個物件提供特定的功能與執行特定的任務(例如:在畫面上顯示訊息)。這些功能以程式碼來表達,即所謂的方法。
現在我們來更深入了解showMessage()方法。
以Swift來說,在類別中宣告一個方法,會使用func關鍵字。func關鍵字後面接著方法名稱。名稱作為方法的識別,並且讓它容易在程式碼中任意被呼叫。有需要的話,方法可以帶入參數(parameter)。參數定義在括號內。以我們的例子來說,這方法是不需要任何的參數,在此情況下只要寫一對空括號即可。
還有一個在方法宣告用到的關鍵字還沒討論到,就是@IBAction關鍵字,這可以讓你將程式原始碼與介面建構器的使用者介面物件做連結。當它被插入宣告的方法前面時,也就是將它公開給介面建構器的意思。因此,此即在之前一章中當你建立Hello World按鈕與程式碼間的連結時,之所以會在彈出式選單中出現了showMessage事件的原因。如果你仍然無法理解的話,請參考這篇。
好的,方法的宣告就說明到這裡,我們討論一下大括號內的程式碼。
這段程式碼實際上就是實踐方法所執行的任務,不過在開發iOS App的時候,我們不需要從頭撰寫所有的功能,例如:你不需要學會如何在畫面上畫出一個提示視窗。只要利用iOS SDK所提供的類別,也就是所謂的「框架(framework)」,可幫你擔負繁重的工作。iOS SDK有各種框架或套件讓你更輕鬆,舉例來說,UIKit框架提供了許多建構與處理App使用者介面的類別。
在這邊我們倚賴UIAlertController來建立Hello World訊息。UIAlertController物件顯示訊息提示給使用者。第一行程式碼是建立UIAlertController物件,類別建立物件的語法與方法呼叫非常相似。先指定類別名稱,接著設定一組屬性(property)的初始值。這裡我們設定標題(title)、顯示訊息(message)與提示的樣式:
let alertController = UIAlertController(title: "Hello World", message: "Hello World", preferredStyle: UIAlertControllerStyle.Alert)
建立完UIAlertController物件後(也就是 alertController),我們呼叫addAction方法來加入一個動作,像是顯示「OK」按鈕的提示。在Swift中呼叫方法的方式,是使用點語法(dot syntax)。
alertController.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil))
你或許想知道要如何尋找一個類別的相關方法或用法。在Xcode中,你可以按下option鍵不放,然後在程式碼中將游標指向類別名稱(例如:UIAlertController),此時會彈出這個類別的敘述,你可以進一步查看類別的參考來學習更多的內容。
UIAlertController物件設定好後,最後一行程式碼是在畫面上顯示訊息。
self.presentViewController(alertController, animated: true, completion: nil)
在Swift中,你可以使用self屬性來參照目前的實體(instance,或者是物件)。要顯示提示訊息,我們要求目前的視圖控制器以動畫方式來呈現alertController。
大部分的情況下,self關鍵字是可以自己決定是否要放的。你也可以像以下這樣簡化程式碼:
presentViewController(alertController, animated: true, completion: nil)
視圖控制器與類別的關係
Xcode是如何知道介面建構器中的視圖控制器與定義在ViewController.swift檔中的ViewController類別連結在一起?
整件事看似沒什麼,但其實不然,你還記得我們在新建Xcode專案時所選擇的模板嗎?就是「Single View Application」模板,當專案模板被採用後,它會自動在介面建構器中建立一個預設的視圖控制器,並且產生了ViewController.swift檔。除此之外,這個視圖控制器自動連結定義在swift檔中的ViewController類別。
如果你切換到Storyboard,並選取視圖控制器。在工具區中,選擇識別檢閱器(Identity Inspector)圖標,你會看到ViewController被設定為「Custom Class(自訂類別)」。這說明了在介面建構器中的物件為何與Swift程式碼內的類別有所關聯。
「Run」按鈕背後的動作原理
本章最後,我要談一下「Run」按鈕。當你點選「Run」按鈕時,Xcode自動地啟動模擬器(Simulator),並且執行你的App,不過,這背後有發生哪些事呢?作為一個程式設計師,你必須要了解整個過程。
這整個程序可以被拆成三個階段:編譯(Compile)、封裝(Package)、執行(Run)。
- 編譯(Compile) – 或許你會認為iOS認識Swift程式碼,實際上,iOS只會讀取機器碼(Machine Code),Swift程式碼只是供開發者撰寫與閱讀使用的,為了讓iOS認識App的原始碼,則必須經過一個轉譯的過程,將Swift 程式碼轉成機器碼。這個過程就稱作「編譯」,Xcode已經有內建編譯器,可以將程式碼做轉譯的動作。
- 封裝(Package) – 除了原始碼以外,一個App通常會包含資源檔,像是圖片、文字檔、聲音檔等等。所有的資源檔會被封裝製作成最終的App。我們通常把這兩個程序稱作「Build」,也就是建置或建構程序。
- 執行(Run) – 這個動作實際上是啟動模擬器並載入你的App。
本章小結
你應該對Hello World App的運作原理有了基本的概念,如果之前沒有程式開發的經驗,或許不易理解我們剛才討論的所有程式觀念。但是別擔心,只要你跟著本書之後的章節來練習撰寫更多的程式碼,並且開發真實的App後,你將會獲得更多Swift與iOS程式設計的概念。
下一篇,我們會將會討論Auto Layout和Size Classes。自從iPhone 6與iPhone 6 Plus釋出之後,Apple的iPhone有了不同的螢幕尺寸,包含3.5英吋、4英吋、4.7英吋與5.5英吋顯示器。究竟如何可以建立一個支援各種螢幕解析度的App?我們將會深入探討。