開發 iOS App 時,有時我們並不需要那麼大的圖片,若能將圖片縮小,將可大幅減少 App 使用的記憶體,或是加快圖片上傳到後台的時間。

從前縮小圖片的程式比較複雜,必須使用到 UIGraphicsImageRenderer。

從 iOS 15 開始,我們有更簡單的方法,呼叫 UIImage 的 preparingThumbnail 即可得到縮小的圖片。

方法 1: 呼叫 preparingThumbnail(of:)

假設變數 image 的型別為 UIImage,呼叫 preparingThumbnail(of:) 時傳入大小 100 * 100,將得到維持比例且不超過 100 * 100 的圖片。比方原本圖片大小是 400 * 200,preparingThumbnail(of:) 回傳的圖片大小將是 100 * 50。

let size = CGSize(width: 100, height: 100)
let thumbnailImage = image.preparingThumbnail(of: size)

方法 2: 呼叫 byPreparingThumbnail(of:)

function byPreparingThumbnail(of:) 是 async function,它可在背景縮小圖片。假設變數 image 的型別為 UIImage, byPreparingThumbnail(of:) 將回傳縮小的圖片。

Task {
let size = CGSize(width: 100, height: 100)
let thumbnailImage = await image.byPreparingThumbnail(ofSize: size)
}

方法 3: 呼叫 prepareThumbnail(of:completionHandler:)

在背景縮小圖片。假設變數 image 的型別為 UIImage,從 completionHandler 的參數 thumbnailImage 可取得縮小的圖片。

let size = CGSize(width: 100, height: 100)
image.prepareThumbnail(of: size) { thumbnailImage in
DispatchQueue.main.async {

}
}

--

--

最近兔子很紅,我們也來寫個 App,複製這隻兔子,換掉他手上的東西吧。

換掉的方法有許多,比方

  • 從 segment control 選擇。
  • 從 text filed 輸入內容。
  • 手勢觸發,比方 swipe 或 tap。

注意: 小小的兔子力氣不大,只能拿兩種東西:

  • 簡單版: emoji
  • 進階版: 圖片

在字串裡包含圖片可利用 NSTextAttachment,方法可參考以下連結。

--

--

當我們在 Interface Builder 設計 App 畫面時,有時會不容易看出元件的佔據的空間,此時可另外打開 Bounds Rectangles 或 Layout Rectangles,讓元件顯示藍色的長方形邊框,方法如下:

Bounds Rectangles

勾選 Editor > Canvas > Bounds Rectangles。

如下圖所示,view & label 都出現了藍色的長方形邊框。別擔心,邊框只會在 Interface Builder 顯示, App 執行時是看不到的。

--

--

開發 iOS App 時,我們時常會利用 optional 儲存資料。不過當 optional 要變成字串時,記得要取值,否則產生的字串會多出奇怪的 Optional( )

以下讓我們看看不取值造成的可怕故事。

let song: String? = "今天情人節"
let urlString = "https://itunes.apple.com/search?term=\(song)"
print(urlString)

我們想從 iTunes API 查詢歌曲資訊,在 API 網址裡傳入 song 儲存的歌名。以上程式不會產生任何紅色錯誤,但是它會產生下圖的黃色警告,因為 \() 的內容是 optional。

雖然黃色警告可以不理,但是更可怕的是 urlString 的內容並不是我們想要的結果,我們想要的是 https://itunes.apple.com/search?term=今天情人節,得到的卻是

https://itunes.apple.com/search?term=Optional("今天情人節")

,多了 Optional( )。

\( ) 裡傳入 optional 時,產生的字串會多出 Optional( ),因此千萬要記得, \( ) 傳入 optional 時要取值。

  • 方法1: 使用 optional binding
let song: String? = "今天情人節"
if let song {
let urlString = "https://itunes.apple.com/search?term=\(song)"
print(urlString)
}
  • 方法2: 使用 nil coalescing
let song: String? = "今天情人節"
let urlString = "https://itunes.apple.com/search?term=\(song ?? "")"
print(urlString)

--

--

當我們從 Interface Builder 加入 button,然後再連結 IBOutlet,想另外從程式修改 button 時,必須特別注意 button 的 Style,因為它將深深影響我們程式的寫法。

  • 當 Style 為 Plain,Gray,Tinted 或 Filled,它將採用 iOS 15 發明的 UIButton.Configuration 設定內容。
  • 當 Style 為 Default,它將採用舊版的方法設定內容。

從 Interface Builder 的 Objects library 可看到有 4 種 button。

這四種 button 的差異在於 Style。

--

--

彼得潘的 iOS App Neverland

彼得潘的 iOS App Neverland

彼得潘的iOS App程式設計入門,文組生的iOS App程式設計入門講師,彼得潘的 Swift 程式設計入門,App程式設計入門作者,http://apppeterpan.strikingly.com

Following