iT邦幫忙

2025 iThome 鐵人賽

DAY 6
0
生成式 AI

iOS? AI-Yes!:用 Vide Coding 加速我的 Swift 學習曲線系列 第 6

Day 6 - 畫面佈局初探:在 XIB 中設定第一個元件與 Auto Layout 約束

  • 分享至 

  • xImage
  •  

昨天,我們成功建立了一個 MainViewController.swift 檔案與其對應的 .xib 檔案。這個 .xib 檔案,就是我們今天的畫布。

今天,我們將在這塊「數位畫板」上,放置我們的第一個 UI 元件,並學習如何使用 Auto Layout 約束,讓它無論在哪個尺寸的 iPhone上,都能顯示在我們想要的位置。

Xcode 的神奇魔法

我點開 MainViewController.xib,從元件庫隨便拖了一個 UILabel 到畫布的正中央。我心想,先在預設的 iPhone 16 Pro 模擬器上看看效果。按下 Command + R,App 啟動後,標籤完美地出現在螢幕中央。

接下來模擬器換成小尺寸的 iPhone SE,再次執行。

  • 困惑點:在 iPhone SE 這麼小的螢幕上,標籤依然完美地保持在正中央!

    這完全顛覆了我從一些舊資料中讀到的「版面會跑掉」的警告。這讓我陷入了更深的困惑:如果 Xcode 這麼聰明,那大家為什麼還要那麼辛苦地學習 Auto Layout?這種看不見的「魔法」可靠嗎?


揭開魔法的面紗:向 AI 提問

  • AI 協作

    • 我的 Prompt:我是一個 iOS 新手。我發現,我在 XIB 裡拖曳一個 UILabel 到畫面的正中央,沒有加上任何 Auto Layout 約束,但在不同尺寸的 iPhone 模擬器上運行時,它都能保持置中。這背後是什麼原理?如果它能自動運作,我為什麼還需要手動設定約束?請簡單說明

    AI 的回答

    您好!這是一個非常好的問題,也是許多 iOS 新手會遇到的共同疑惑。您觀察到的現象背後,其實牽涉到 iOS 介面佈局(Layout)系統的演進歷史。

    簡單來說,您看到的「自動置中」是一種舊版佈局系統的預設行為,但它並不如您想像中那麼可靠和強大。


    背後的原理:Autoresizing Mask

    在 Auto Layout 成為主流之前,iOS 使用一種稱為 Frame-Based Layout 的佈局方式。開發者需要手動計算並設定每個視圖(View)的 frame 屬性,也就是它的 xy 座標、寬度和高度。

    為了讓這種寫死座標的方式能稍微適應不同尺寸的螢幕,蘋果引入了一個叫做 Autoresizing Mask(自動調整大小遮罩)的機制。

    當您從 Interface Builder(XIB 或 Storyboard)中拖曳一個元件(如 UILabel)到畫面上,並且沒有為它添加任何 Auto Layout 約束時,Xcode 會預設啟用這個舊的 Autoresizing Mask 機制。

    這個機制是如何運作的呢?

    您可以把它想像成,您的 UILabel 被放在一個容器(父視圖)中,並透過一些「彈簧」和「支架」與容器的邊緣連接。

    • 彈簧 (Flexible Margin/Size):可以被拉伸或壓縮。
    • 支架 (Fixed Margin/Size):保持固定距離或大小。

    當您把 UILabel 拖到畫面的正中央時,系統會「猜測」您的意圖,並設定一個如下的 Autoresizing Mask:

    • 上下左右的邊距(Margin)都是彈簧。
    • UILabel 本身的寬度和高度是支架(固定大小)。

    當您在不同尺寸的 iPhone 上運行時:

    1. 螢幕變寬了:左右兩邊的「彈簧」會一起被拉長,因為它們是彈性的。由於兩邊拉長的長度相同,所以 UILabel 看起來仍然在水平方向的中央。
    2. 螢幕變高了:上下兩邊的「彈簧」會一起被拉長,所以 UILabel 看起來仍然在垂直方向的中央。

    這就是您觀察到「它都能保持置中」的根本原因。這個行為是由一個重要的屬性 translatesAutoresizingMaskIntoConstraints 控制的。當您不加任何約束時,這個屬性預設為 true,系統就會在執行時期將這個 Autoresizing Mask「翻譯」成一組臨時的、隱含的 Auto Layout 約束,來模擬舊的行為。


    為什麼還需要手動設定約束?

    既然它能「自動」運作,為什麼我們還需要大費周章地去學習和設定 Auto Layout 約束呢?

    因為 Autoresizing Mask 的「猜測」非常脆弱功能有限,在真實世界的 App 開發中很快就會遇到瓶頸。

    1. 它無法處理複雜的相對關係

    Autoresizing Mask 只能定義一個視圖與其「父視圖」的關係。如果畫面上有兩個 UILabel,您希望它們之間永遠相距 10 點(points),Autoresizing Mask 完全辦不到。它不知道這兩個 UILabel 之間有任何關聯。

    例子:您在置中的標籤旁放一個按鈕。當螢幕變寬時,標籤和按鈕會各自根據自己的「彈簧」移動,它們之間的距離會改變,甚至可能發生重疊。

    2. 它在螢幕旋轉時經常會失效

    從直向(Portrait)轉為橫向(Landscape)時,螢幕的寬高比會發生劇烈變化。Autoresizing Mask 那套簡單的「彈簧與支架」模型常常無法正確處理這種劇變,導致元件位置跑掉,不再是您預期的樣子。

    3. 它無法適應內容的動態變化

    如果您的 UILabel 因為多國語系(Localization)或使用者設定(Dynamic Type)而導致文字長度改變,您可能希望它能自動變寬,並推開旁邊的元件。Autoresizing Mask 做不到,它的寬高預設是固定的「支架」。


    結論:從「猜測」到「定義」

    您可以這樣理解兩者的差別:

    • 預設行為 (Autoresizing Mask):您把元件放在一個大概的位置,然後跟系統說:「你幫我猜猜看,當螢幕變化的時候,它該怎麼動。」這在最簡單的情況下有效,但非常模糊且不可靠。
    • 手動設定 Auto Layout 約束:您明確地告訴系統這個元件必須遵守的規則。這不是猜測,而是精確的定義。例如:
      • 「我命令此標籤的水平中心」必須永遠等於「其父視圖的水平中心」
      • 「我命令此標籤的垂直中心」必須永遠等於「其父視圖的垂直中心」

    當您在 Interface Builder 中為一個視圖加上第一個手動約束時,Xcode 就會自動將它的 translatesAutoresizingMaskIntoConstraints 屬性設為 false,停用舊的 Autoresizing Mask 機制,並完全交由您定義的 Auto Layout 約束來決定佈局。

    總結來說,您看到的自動置中是 Autoresizing Mask 這個舊機制的「遺產」,它在簡單情境下提供了一種便利。但若要打造一個能夠適應各種螢幕尺寸、方向和內容變化的現代化、穩健的 iOS App,學習並使用 Auto Layout 來明確定義介面規則是不可或缺的專業技能。

    • 我的理解是約束真的非常重要,如何拉約束是非常大的一門學問!

使用 Align 親手建立約束

現在,我要親手建立約束,讓元件的位置由我說了算。

我的操作步驟:

我回到 MainViewController.xib,按照 AI 的指示:

  1. 首先,點選畫布上的 UILabel

  2. 接著,點擊 Xcode 編輯器右下角的「Align (對齊)」按鈕。
    image

  3. 在跳出的選單中,我勾選了 Horizontally in ContainerVertically in Container

  4. 最後,點擊 Add 2 Constraints

    image 1


連結畫面與程式碼 - 認識 @IBOutlet

下一個問題:版面問題解決了。但如果我想用程式碼去改變這個 Label 的文字,該怎麼辦?

第一步:打開助理編輯器(按ctrl + option + command + enter)

image 2

第二步:按著 control 並拉元件 Label 到 MainViewController.swift 裡面,並取名為 lbTitle
image 3
image 4

第三步:改寫程式碼

class MainViewController: UIViewController {

    // 透過 Control + 拖曳
    @IBOutlet weak var lbTitle: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 透過 IBOutlet,用程式碼改變 Label 的文字
        lbTitle.text = "Justin"
    }
}

效果大概是長這樣 ⬇️
image 5

今天我們從一個看似正常的現象出發,透過與 AI 的對話,一路追根究柢,不僅學會了在 XIB 中設定 Auto Layout 約束、用 @IBOutlet 連結程式碼

明天,我們將探討 iOS 開發中最經典的架構模式:MVC (Model-View-Controller),為我們未來的專案打下穩固的架構基礎。


上一篇
Day 5 - 專案啟動與架構解析:App 如何從無到有並開始呼吸?
系列文
iOS? AI-Yes!:用 Vide Coding 加速我的 Swift 學習曲線6
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言