解析 View Controller 生命週期:使用 viewDidLayoutSubviews 的時機


編輯的話:之前,我們新增了新的教學系列,來回答 iOS App 開發上的常見問題。對初學者來說,其中一個問題就是何時該使用 viewDidLayoutSubviews。在本次的教學裡,Kelvin 將會探討一些 View Controller 生命週期裡的方法,並解釋 viewDidLayoutSubviews 方法的用途。

我們這些 iOS 開發者總是會擔心自己缺乏某些知識、或是覺得自己技術不足;但我可以告訴所有開發者,你們知道的其實很多,你只需要對自己有耐性,繼續努力完成日常工作、或是維持撰寫程式這個興趣就好。

經常有文章列出很多成為 iOS 開發者前應該知道的東西,但是要懂多少才算是足夠呢?今天我們將會專注在一些「小事情」上,讓我們對基礎知識有更清晰的了解。我們會先了解那些每天都在新專案中用到的小小程式碼,因為我相信小事情會給我們大智慧。

在本次的教學裡,我們將會了解 viewDidLoadviewDidAppear 以及 viewDidLayoutSubviews 的不同之處。讀過教學以後,我們希望你對此有更深入的理解,並可以有效地使用文中提及的方法。

我會試著用不同的方式來解釋這三個方法,因為我們都知道有時文字敘述真的很難懂。你可能會看到重複的解釋,因為我會試著用簡單的詞彙來演繹,幫助你以另一個角度理解它。

甚麼是 viewDidLoad?

你應該對這個方法十分熟悉,至少也大致了解這個方法在每次執行程式碼時的操作。每次建立專案時,你都會看到這程式碼;即使你沒看過也沒關係。

Apple 對於 viewDidLoad 的定義,是它會在 Controller 的視圖被載入記憶體後 被呼叫。簡單來說,即是第一個載入的方法。

你可能會想:到底在甚麼情況下會充分利用這個方法?答案是:依你希望 App 首先載入的東西而定,例如:你想把背景顏色從白色更換成藍色。

view controller lifecycle-1

甚麼是 viewDidAppear?

你或許有使用過這個方法,甚至了解它的內容,不過可能有些人是第一次看到它。無論經驗多少,你至少會在專案裡用到這個方法一次。

Apple 將其定義為「通知 View Controller 視圖已經被加進視圖階層裡。」換句話說,就是當畫面呈現在使用者眼前時,就呼叫這個方法。

viewDidAppearviewDidLoad 的不同之處,在於每次進入畫面時 viewDidAppear 就會被呼叫,而 viewDidLoad 只會在 App 加載時被呼叫一次。讓我做個簡單的實驗來幫助你了解其運作方法吧!

view controller lifecycle-animate-1

讓我用一個更實際的例子來解釋。你可以看到在 viewDidAppear 裡,我建立了一個圖像,放置於在螢幕外 300pt 的位置,然後使用一個動畫來讓圖像從螢幕外側移動到螢幕底部置中的位置。

view controller lifecycle-animate-2

透過上面的範例動畫,現在你應該知道 viewDidAppear 會一直重複被呼叫,而 viewDidLoad 則只被呼叫一次而已。

甚麼是 viewDidLayoutSubviews?

Apple 針對 viewDidLayoutSubviews 給了一個很好的解釋:呼叫 viewDidLayoutSubviews,就可以通知 View Controller 它的視圖剛放置好子視圖內。換句話說,每次當視圖更新、旋轉、更動或是 bounds change 時就會呼叫 viewDidLayoutSubviews。這段解釋的關鍵字就是 bounds change

但是要知道,viewDidLayoutSubviews 只會在視圖上所有 Auto Layout 設定或是大小自動計算完成後才會執行,這表示當每次視圖的大小改變或是佈局重新計算時就會呼叫 viewDidLayoutSubviews 方法。

每當你 Build App 時,viewDidLayoutSubviews 就會在 viewDidLoad 之後執行,因為 viewDidLayoutSubviews 是在佈局計算後被呼叫。然後當你旋轉 App 時,viewDidLayoutSubviews 就會再次執行,不過這次只會在橫式與直式互換時執行,而從左換到右時則不會執行。你可以用模擬器上的 Hardware > Orientation 設定來試試。

view controller lifecycle-animate-3

不過讓我們來思考一下。這方法真正的用途是什麼呢?下面的圖片就展示了使用 viewDidLayoutSubviews 的結果和差異。你可以試著不實作 viewDidLayoutSubviews 方法來試試下面的範例,就可以看到如下圖所示的不同之處,請注意寬度的變化。

view controller lifecycle-2

讓我來解釋一下這個方法的過程,其中有幾項你需要注意的事。

  1. 這段程式碼會印出按鈕的初始位置
  2. 這段程式碼會以新的位置取代初始位置
  3. 這是按鈕在螢幕上的座標位置 ── 數值在 viewDidLoad 中讀取
  4. 你會看到 viewDidLoad position 的位置被 viewDidLayoutSubviews 的數值覆寫,而且當你旋轉螢幕至垂直狀態時,寬度會有所變化

view controller lifecycle-3

現在你心中的最後一個問題大概是:到底什麼時候要覆寫這個方法。我肯定依據你先前所看到的範例,你可能已經注意到 viewDidLayoutSubviews 總是覆寫 viewDidLoad

最後,如果你還是覺得很難理解,我希望最後這個範例能夠讓你對照 viewDidLoadviewDidAppear 以及 viewDidLayoutSubviews 是如何運作的,你亦可以重新閱讀本篇文章並跟著實作。如果想要閱讀並理解完整的程式碼的話,你可以從 GitHub 下載。

view controller lifecycle-animate-4

譯者簡介:楊敦凱-目前於科技公司擔任 iOS Developer,工作之餘開發自有 iOS App同時關注網路上有趣的新玩意、話題及科技資訊。平時的興趣則是與自身專業無關的歷史、地理、棒球。來信請寄到:[email protected]

原文View Controller Lifecycle Explained: When to Use viewDidLayoutSubviews


自學的 iOS 手機程式開發者,最近積極於自己的網站 www.daddycoding.com 上寫教學文章。來自馬來西亞,精通四種語言。如有任何問題,歡迎與他聯絡。

blog comments powered by Disqus
訂閲電子報

訂閲電子報

AppCoda致力於發佈優質iOS程式教學,你不必每天上站,輸入你的電子郵件地址訂閱網站的最新教學文章。每當有新文章發佈,我們會使用電子郵件通知你。

已收你的指示。請你檢查你的電郵,我們已寄出一封認證信,點擊信中鏈結才算完成訂閱。

Shares
Share This