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 16 App 程式設計實戰心法》、《iOS 16 App程式設計進階攻略》以及《精通SwiftUI》。曾任職於HSBC, FedEx等跨國企業,專責軟體開發、系統設計。2012年創立AppCoda技術部落格,定期發表iOS程式教學文章。現時專注發展AppCoda業務,致力於iOS程式教學、產品設計及開發。你可以到推特與我聯絡。
評論
更多來自 AppCoda 中文版
如何在 SwiftUI 使用 Preview Macro
SwiftUI 框架

如何在 SwiftUI 使用 Preview Macro

SwiftUI 中的預覽(Preview)功能允許開發人員在不運行應用程序於設備或模擬器上的情況下,實時查看App的外觀。這個功能對於那些希望快速迭代設計並確保一切看起來和運作如預期的開發人員來說非常有用。隨著 iOS 17 中引入了巨集(Macro)的功能,預覽功能變得更加強大和靈活,提供了更多的自定義和靈活性。在本教學中,我們將探索如何在 SwiftUI 中使用新的預覽巨集(Preview Macro)
很好! 你已成功註冊。
歡迎回來! 你已成功登入。
你已成功訂閱 AppCoda 中文版 電子報。
你的連結已失效。
成功! 請檢查你的電子郵件以獲取用於登入的連結。
好! 你的付費資料已更新。
你的付費方式並未更新。