Mehrere Bilder via PhotosPicker auswählen

Ergänzend zum letzten Artikel, in dem es um die grundlegende Konfiguration und Nutzung der neuen PhotosPicker-View ging, stelle ich euch an dieser Stelle vor, wie ihr mehrere Bilder mittels PhotosPicker auswählen und verarbeiten könnt.

Die wichtigste und ausschlaggebende Änderung betrifft den selection-Parameter bei Initialisierung eines PhotosPickers. Um mehrere Bilder auswählen zu können, muss der Parameter einem Binding entsprechen, das auf ein Array von PhotosPickerItem-Instanzen verweist (statt auf ein Optional vom Typ PhotosPickerItem). Die vom Nutzer ausgewählten Bilder landen dann in jenem Array und lassen sich von dort aus weiter verarbeiten.

Eine entsprechend simple Konfiguration eines PhotosPickers kann so aussehen wie im folgenden Listing:

import PhotosUI
import SwiftUI

struct ContentView: View {
    @State private var selectedItems = [PhotosPickerItem]()
    
    var body: some View {
        PhotosPicker(selection: $selectedItems, matching: .images) {
            Label("Select photos", systemImage: "plus.app")
        }
    }
}

Nun steht noch die Verarbeitung der gewählten Bilder aus. Dazu kommt erneut der onChange(of:perform:)-Modifier zum Einsatz, über den man das selectedItems-Array überwacht. Ändert es sich, erhält man aber nun nicht ein einzelnes PhotosPickerItem, sondern ein Array davon. Entsprechend muss man alle Elemente dieses Arrays durchlaufen und daraus die passenden Data-Instanzen beziehen.

Wie man mit den Bilddaten in Form der Data-Instanzen weiter umgeht, hängt individuell vom Anwendungsfall ab. Das nachfolgende Listing demonstriert einmal eine mögliche Implementierung von onChange(of:perform:), in der die ausgewählten Bilddaten in einem separaten Status namens imagesData gesichert werden. Auf Basis dieses Arrays werden innerhalb der View alle gewählten Bilder angezeigt.

import PhotosUI
import SwiftUI

struct ContentView: View {
    @State private var imagesData = [Data]()
    
    @State private var selectedItems = [PhotosPickerItem]()
    
    var body: some View {
        VStack {
            PhotosPicker(selection: $selectedItems, matching: .images) {
                Label("Select photos", systemImage: "plus.app")
            }
            .onChange(of: selectedItems) { newSelectedItems in
                Task {
                    var itemsData = [Data]()
                    for item in newSelectedItems {
                        if let itemData = try? await item.loadTransferable(type: Data.self) {
                            itemsData.append(itemData)
                        }
                    }
                    await MainActor.run {
                        self.imagesData = itemsData
                    }
                }
            }
            Divider()
            ForEach(imagesData, id: \.self) { data in
                if let uiImage = UIImage(data: data) {
                    Image(uiImage: uiImage)
                        .resizable()
                        .scaledToFit()
                }
            }
            Spacer()
        }
    }
}

Fazit

Es ist erfreulich simpel, über einen PhotosPicker statt nur einem Bild alternativ mehrere Bilder auswählen zu können. Die Steuerung erfolgt vollständig bei der Initialisierung über den selection-Parameter. Handelt es sich um ein Binding vom Typ PhotosPickerItem?, kann nur ein Element gewählt werden, im Falle des Typs [PhotosPickerItem] mehrere. In letzterem Fall erweitert man zusätzlich noch die Logik, um die Bilddaten aus allen ausgewählten Elementen zu extrahieren.

Euer Thomas


Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert