SwiftUI 框架

如何在 iOS App 中嵌入照片選擇器

在本教學中,我將向你展示如何使用改進的PhotosPicker視圖實現內嵌的照片選取器。
如何在 iOS App 中嵌入照片選擇器
如何在 iOS App 中嵌入照片選擇器
In: SwiftUI 框架

從iOS 16開始,SwiftUI 引入了一個名為PhotosPicker的本地照片選取器視圖。如果你的App需要訪問使用者的照片庫,PhotosPicker視圖可以無縫地管理照片選擇過程。這個內建視圖提供了非凡的簡單性,讓開發人員只需幾行程式碼就可以呈現選取器並處理圖像選擇。

當呈現PhotosPicker視圖時,它會在你的應用界面之上以一個獨立的頁面形式展示照片相冊。在 iOS 的早期版本中,你無法自定義或更改照片選取器視圖的外觀,以符合你的應用程序佈局。然而,蘋果在 iOS 17 中對PhotosPicker視圖進行了增強,使開發人員可以將其無縫嵌入應用程序中。此外,你可以使用標準的 SwiftUI 修飾器(如.frame.padding)來修改其大小和佈局。

在本教學中,我將向你展示如何使用改進的PhotosPicker視圖實現內嵌的照片選取器。

重温 PhotosPicker

要使用 PhotosPicker 視圖,你可以首先聲明一個狀態變量來存儲照片選擇,然後通過將綁定傳遞給該狀態變量來實例化一個 PhotosPicker 視圖。以下是一個示例:

import SwiftUI
import PhotosUI

struct ContentView: View {
    
    @State private var selectedItem: PhotosPickerItem?
    
    var body: some View {
        PhotosPicker(selection: $selectedItem,
                     matching: .images) {
            Label("Select a photo", systemImage: "photo")
        }
    }
}

matching 參數允許你指定要顯示的資源類型。在這裡,我們只選擇顯示圖像。在閉包中,我們使用 Label 視圖創建一個簡單的按鈕。

在選擇一張照片後,照片選取器會自動關閉,並將所選的照片項存儲在 selectedItem 變數中,該變數的類型是 PhotosPickerItem。要從項目中加載圖像,可以使用 loadTransferable(type:completionHandler:) 方法。你可以附加 onChange 修飾器來監聽 selectedItem 變數的更新。每當有變化時,你可以調用 loadTransferable 方法來加載資源數據,像這樣:

@State private var selectedImage: Image?

.
.
.

.onChange(of: selectedItem) { oldItem, newItem in
    Task {
        if let image = try? await newItem?.loadTransferable(type: Image.self) {
            selectedImage = image
        }
    }
}

在使用 loadTransferable 時,需要指定要檢索的資源類型。在這種情況下,我們使用 Image 類型來直接加載圖像。如果操作成功,該方法將返回一個 Image 視圖,可以直接用於將照片渲染到屏幕上。

if let selectedImage {
    selectedImage
        .resizable()
        .scaledToFit()
        .padding(.horizontal, 10)
}

實現內嵌的 PhotosPicker

現在你應該明白如何使用 PhotosPicker,讓我們看看如何將其嵌入到我們的演示應用程序中。我們將用內嵌的 Photos 選取器替換「選擇一張照片」按鈕。更新後的 PhotosPicker 版本帶有一個名為 photosPickerStyle 的新修飾符。通過指定 .inline 的值,Photos 選取器將自動嵌入應用程序中:

.photosPickerStyle(.inline)

你還可以附加標準的修飾器,如 .frame.padding,來調整選取器的大小。

預設情況下,選取器的頂部附件是導航欄,底部附件是工具欄。要禁用這兩個欄,你可以應用 photosPickerAccessoryVisibility 修飾器:

.photosPickerAccessoryVisibility(.hidden)

此外,你還可以選擇性地隱藏其中一個附件:

.photosPickerAccessoryVisibility(.hidden, edges: .bottom)

處理多個照片選擇

目前,Photos 選取器只允許用戶選擇單張照片。要啟用多個選擇,你可以通過將 selectionBehavior 設置為 .continuous.continuousAndOrdered 來選擇連續選擇行為:

PhotosPicker(selection: $selectedItems, 
						 maxSelectionCount: 5, 
             selectionBehavior: .continuousAndOrdered,
             matching: .images) {
    Label("Select a photo", systemImage: "photo")
}

如果你希望限制可選擇的項目數量,你可以使用 maxSelectionCount 參數來指定最大計數。

一旦使用者選擇了一組照片,它們將存儲在 selectedItems 數組中。selectedItems 數組已經被修改以容納多個項目,並且現在的類型是 PhotosPickerItem

@State private var selectedItems: [PhotosPickerItem] = []

要加載所選的照片,你可以像這樣更新 onChange 閉包:

.onChange(of: selectedItems) { oldItems, newItems in
    
    selectedImages.removeAll()
    
    newItems.forEach { newItem in
    
        Task {
            if let image = try? await newItem.loadTransferable(type: Image.self) {
                selectedImages.append(image)
            }
        }

    }
}

我使用了一個 Image 數組來存儲獲取的圖像。

@State private var selectedImages: [Image] = []

要顯示選擇的圖像,你可以使用水平滾動視圖(horizontal scroll view)。以下是可以放在 VStack 視圖的開頭的示例程式碼:

if selectedImages.isEmpty {
    ContentUnavailableView("No Photos", systemImage: "photo.on.rectangle", description: Text("To get started, select some photos below"))
        .frame(height: 300)
} else {
    
    ScrollView(.horizontal) {
        LazyHStack {
            ForEach(0..<selectedImages.count, id: \.self) { index in
                selectedImages[index]
                    .resizable()
                    .scaledToFill()
                    .frame(height: 250)
                    .clipShape(RoundedRectangle(cornerRadius: 25.0))
                    .padding(.horizontal, 20)
                    .containerRelativeFrame(.horizontal)
            }
            
        }
    }
    .frame(height: 300)
}

在 iOS 17 中,引入了一個名為 ContentUnavailableView 的新視圖。建議在無法顯示視圖的內容的情況下使用此視圖。因此,當沒有選擇照片時,我們使用 ContentUnavailableView 來呈現簡潔且信息豐富的消息。

總結

在 iOS 17 中,蘋果對原生的 Photos 選取器進行了改進。現在,你可以輕鬆地在你的 App 中包含它,而不需要使用單獨的表單。本教程解釋了更新的 PhotosPicker 視圖所帶來的新修飾器,並展示了如何創建內嵌的照片選取器。

如果你喜歡閱讀本教程並且想深入研究SwiftUI,你可以查看我們的《精通SwiftUI》書籍。

作者
Simon Ng
軟體工程師,AppCoda 創辦人。著有《iOS 17 App 程式設計實戰心法》、《iOS 17 App程式設計進階攻略》以及《精通SwiftUI》。曾任職於HSBC, FedEx等跨國企業,專責軟體開發、系統設計。2012年創立AppCoda技術部落格,定期發表iOS程式教學文章。現時專注發展AppCoda業務,致力於iOS程式教學、產品設計及開發。你可以到推特與我聯絡。
評論
更多來自 AppCoda 中文版
如何使用 Vision APIs 從圖像中辨識文字
AI

如何使用 Vision APIs 從圖像中辨識文字

Vision 框架長期以來一直包含文字識別功能。我們已經有詳細的教程,向你展示如何使用 Vision 框架掃描圖像並執行文字識別。之前,我們使用了 VNImageRequestHandler 和 VNRecognizeTextRequest 來從圖像中提取文字。 多年來,Vision 框架已經顯著演變。在 iOS 18 中,Vision
iOS 18更新:SwiftUI 新功能介紹
SwiftUI 框架

iOS 18更新:SwiftUI 新功能介紹

SwiftUI的技術不斷演進,每次更新都讓 iOS 應用程式開發變得更加便捷。隨著 iOS 18 Beta 的推出,SwiftUI 引入了多個令人興奮的新功能,使開發者僅需幾行程式碼即可實現出色的效果。 本教學文章旨在探索這個版本中的幾項主要改進,幫助你了解如何運用這些新功能。 浮動標籤列 (Floating Tab Bar)SwiftUI中的標籤視圖(Tab
很好! 你已成功註冊。
歡迎回來! 你已成功登入。
你已成功訂閱 AppCoda 中文版 電子報。
你的連結已失效。
成功! 請檢查你的電子郵件以獲取用於登入的連結。
好! 你的付費資料已更新。
你的付費方式並未更新。