iOS 開發 #9 Alert 與 Sheet 的開啟方式 (上) Sheet

Han
彼得潘的 Swift iOS / Flutter App 開發教室
7 min readAug 9, 2024

前言

一個好的 APP 除了要有精美的畫面,也要有良好的提示效果,若想使用小視窗來提供用戶與當前情境畫面的細部操作可以使用 Sheet ,而提示的效果可以使用 Alert

Sheet

Sheet 以可調節的高度來做顯示。它常用於顯示需要用戶注意的內容或提供額外的操作選項

原則

  • 輔助性質的 : 用來輔助主畫面中的 UI 元件
  • 有彈性的 : 可以用來顯示各式各樣的元件與佈局
  • 好操作的 : 位置上,應該讓用戶能輕易點選到

首先先到 storyboard 建立兩個 View Controller

這邊為了方便辨識我把兩個 View Controller 各加上 Label ,一個打上 Page 1 ,一個打上 Sheet

這邊我打算按下 Page 1Button 後會打開 Sheet ,所以從 Page 1ButtonSegueSheet

接著在跳出的小視窗選擇 Present Modally

這樣就完成簡單的 Sheet

我知道這樣是沒辦法滿足各位的求知慾的,所以接下來試試用寫 Code 的方式來修改 Sheet

從兩個 View Controller 中間的箭頭拉 SegueView Controller

接著輸入這段 Code

let controller = SheetViewController(coder: coder)
return controller

這時複製進去後發現報錯了

這是代表他找不到 SheetViewController ,所以建立一個名叫 SheetViewController ,然後把他定義為 UIViewController ,如果不知道他要怎麼定義或是懶得打的話,我把 Code 打在這邊

import UIKit

class SheetViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
}

把上面的 Code 複製到 SheetViewController 後,接著到 storyboard 的 sheet 頁面綁定 SheetViewController

這樣我們就可以對 Sheet 做一些設定了

第一個我們先來設定 Sheet 顯示的高度

if let sheet = controller?.sheetPresentationController {
sheet.detents = [.medium()]
}

先用 if let 來取得 sheetPresentationController 後,透過 .detents 這個 property 來設定 Sheet 的高度

Sheet 高度模式

  • .large :這個會使 Sheet 顯示的高度會幾乎填滿整個螢幕
  • .medium :這會使 Sheet 顯示一半高度的畫面
  • .custom :這可以自定義 Sheet 的顯示高度

Sheet 頂部的抓取條

.prefersGrabberVisible 使用這個 property 可以設定抓取條是否可見

Sheet 圓角

.preferredCornerRadius 使用這個 property 可以調整 Sheet 頂部的圓角弧度

這時你應該會有個疑問 (應該會有疑問……對吧?)

那如果我想要在 Sheet 中放入 Text Field ,在 Sheet 裡的 Text Field 中輸入資料後傳回 View Controller ,這樣該怎麼做?

這邊需要先提到閉包的概念

閉包是什麼其實我也不是很懂,所以我請我最好的工作夥伴 ChatGPT 來解釋:

閉包的概念

閉包(Closure)是 Swift 中的一種語法,用來封裝一段可以在稍後執行的程式碼。閉包可以捕捉並儲存程式碼塊中的變數和常數,因此它們在 Swift 開發中非常強大和靈活

閉包本質上就是一個可以被傳遞和使用的函式,這個函式可以從上下文中捕捉到變數或常數。閉包類似於其他語言中的匿名函式或 lambda 表達式

閉包的基本結構

{ (參數列表) -> 返回值型別 in
執行的程式碼
}
  • 參數列表:閉包的輸入參數,就像函式的參數一樣
  • 返回值型別:閉包的返回值型別。如果閉包沒有返回值,可以省略這一部分
  • in:關鍵字,用來分隔閉包的參數和實際執行的程式碼

OK,簡單介紹完閉包的概念後就來試著用閉包來傳值

先到 storyboard 新增一個 Text Field 跟一個 Button

然後到 SheetViewController 綁定 Text FieldOutlet 以及 ButtonIBAction

接著定義一個閉包 var onSubmit: ((String) -> Void)?

IBAction 中用 if let 來取得 input 輸入的值後打上 onSubmit?(input)

接著回到 ViewController 來取得閉包的值

把這段 Code 打上去

controller?.onSubmit = { input in
print(input)
}

之後來看看執行的結果

可以看到按下 Button 後他就會 printText Field 輸入的資料

我這邊只是把我在 iOS 開發 #8 靠著賭博發家致富 — 21點 中使用到的方法拿出來解釋,如果對 Sheet 其他用法有興趣,可以參考一下這篇文章

--

--