Press "Enter" to skip to content

PhotosPicker in SwiftUI 4

Neuerungen der WWDC 2022 – Teil 5

Mit der neuen PhotosPicker-View steht uns jetzt ein natives SwiftUI-Element zur Verfügung, um auf die Foto-Library zugreifen und Bilder auswählen zu können. In diesem Artikel gehe ich auf die grundlegende Funktionsweise von PhotosPicker ein und zeige euch, wie ihr diese neue View nutzen könnt, um ein einzelnes Foto aus der Library auszuwählen und anzuzeigen.

Grundlagen

PhotosPicker nutzt eine Instanz vom Typ PhotosPickerItem, um die vom Nutzer gewählten Fotos abzubilden. Demnach braucht es ein Binding auf eine PhotosPickerItem-Instanz, die man PhotosPicker als Parameter übergibt. PhotosPicker füllt dieses Binding mit den Daten der vom Nutzer gewählten Fotos.

Jenes Binding könnt ihr auf zwei Arten konfigurieren. Falls der Nutzer mehrere Fotos auswählen soll, kommt als zugrundeliegender Status ein Array von PhotosPickerItem-Instanzen zum Einsatz. Soll nur ein einzelnes Bild wählbar sein, reicht als Status ein Optional vom Typ PhotosPickerItem. In diesem Beispiel betrachte ich letztere Variante.

Um eine PhotosPicker-Instanz zu erzeugen, braucht es in der einfachsten Variante nur zwei Parameter:

  • selection: Das Binding auf den PhotosPickerItem-Status, der die Daten zu den ausgewählten Fotos erhält. Wie beschrieben handelt es sich bei dem zugrundeliegenden Typ dieses Bindings entweder um [PhotosPickerItem] (für die Auswahl mehrerer Bilder) oder PhotosPickerItem? (für die Auswahl eines einzelnen Bildes).
  • label: Die Darstellung von PhotosPicker. PhotosPicker ist letztlich ein einfacher Button, dessen Betätigung die Foto-Library öffnet. Mithilfe des label-Parameters legt ihr das Aussehen jenes Buttons fest.

Zusätzlich gibt es noch diverse weitere optionale Parameter, mit denen sich PhotosPicker zusätzlich konfigurieren lässt. Einer davon ist matching. Über ihn legt ihr fest, welche Arten von Dateien aus der Foto-Library auswählbar sein sollen. Ihr habt hier unter anderem die Wahl zwischen Werten wie images, livePhotos oder videos.

Das nachfolgende Listing skizziert einmal beispielhaft die Umsetzung einer einfachen PhotosPicker-Instanz, die lediglich die Auswahl eines einzigen Bildes erlaubt. Wichtig hierbei: PhotosPicker ist Teil des PhotosUI-Frameworks, das entsprechend importiert werden muss.

import PhotosUI
import SwiftUI

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

Zugriff auf das ausgewählte Foto

Der PhotosPicker weist das gewählte Foto dem PhotosPickerItem-Binding zu. So bleibt nun noch zu klären, wie man aus einem PhotosPickerItem heraus auf das zugrundeliegende Bild zugreift.

PhotosPickerItem selbst gewährt uns keinen direkten Zugriff auf das enthaltene Foto, was wohl mit den unterschiedlichen Mediendateien und -formaten zusammenhängt, die PhotosPickerItem unterstützt (es lassen sich ja unter anderen auch Videos auswählen, die anders zu verarbeiten sind als Fotos).

Aus diesem Grund stellt PhotosPickerItem eine Methode namens loadTransferable(type:) zur Verfügung. Ähnlich wie bei der Arbeit mit NSItemProvider fragt man so ab, ob das in PhotosPickerItem enthaltene Medienelement einem spezifischen Typ entspricht. Das generischste Vorgehen besteht darin, gegen den Typ Data zu prüfen und so die tatsächlichen Daten des gewählten Medienelements als Ergebnis zu erhalten. Diese Daten lassen sich dann beliebig weiter verarbeiten (zum Beispiel zur Anzeige eines Bildes via Image-View).

Um mitzubekommen, wann über einen PhotosPicker ein Bild ausgewählt und so das Binding des PhotosPickerItems gesetzt wurde, nutzt man den onChange(of:perform:)-Modifier. Das nachfolgende Listing zeigt einmal ein vollständiges Beispiel zum Einsatz des PhotosPicker inklusive Anzeige des gewählten Fotos. Dazu werden die ausgewerteten Bilddaten einem Status namens imageData zugewiesen, die wiederum zur Darstellung des gewählten Bildes innerhalb der View dienen.

import PhotosUI
import SwiftUI

struct ContentView: View {
    @State private var imageData: Data?
    
    @State private var selectedItem: PhotosPickerItem?
    
    var body: some View {
        VStack {
            PhotosPicker(selection: $selectedItem, matching: .images) {
                Label("Select a photo", systemImage: "plus.app")
            }
            .onChange(of: selectedItem) { newValue in
                Task {
                    if let data = try? await newValue?.loadTransferable(type: Data.self) {
                        await MainActor.run {
                            self.imageData = data
                        }
                    }
                }
            }
            Divider()
            if let imageData, let uiImage = UIImage(data: imageData) {
                Image(uiImage: uiImage)
                    .resizable()
                    .scaledToFit()
            }
            Spacer()
        }
    }
}

Fazit

PhotosPicker ist eine erfreuliche Ergänzung innerhalb des SwiftUI-Frameworks. Die Konfiguration der View ist simpel und man erhält so schnell und unkompliziert Zugriff auf die Foto-Library. Zwar erscheint das Auswerten der gewählten Bilddaten über die loadTransferable(type:)-Methode eines PhotosPickerItem recht aufwendig, erfüllt aber ihren Zweck. Und hat man dieses Vorgehen erst einmal verinnerlicht, stellt es bei der zukünftigen Arbeit mit PhotosPicker und PhotosPickerItem auch keine Hürde mehr da.

Euer Thomas

3 Kommentare

  1. Günter Laudahn Günter Laudahn

    Hallo Thomas,
    ich habe PhotosPicker nachgebaut und ich bekomme aber nicht die Bilder meiner photoslibrary angezeigt, sondern die Fotos aus deinem Beispiel. Warum?

    • Hallo Günter,

      testest du das Beispiel im Simulator? Im Simulator sind die Bilder aus meinem Video „vorinstalliert“. Somit bekommen wir die alle zu sehen, wenn wir im Simulator auf die Foto-Library zugreifen. Bei Installation auf einem Endgerät sollten stattdessen die auf dem zugrundeliegenden iPhone vorhandenen Bilder auftauchen.

      Viele Grüße,
      Thomas

      • Günter Laudahn Günter Laudahn

        Danke für die promte Antwort🙋‍♂️

Schreibe einen Kommentar

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

Impressum

Thomas Sillmann
Kettererstraße 6
D-63739 Aschaffenburg
E-Mail: contact@thomassillmann.de
Mobil: +49 (0) 151 65125650
Web: https://www.thomassillmann.de/

Inhaltlich Verantwortlicher gemäß §55 Abs. 2 RStV: Thomas Sillmann (Anschrift siehe oben)

Haftungshinweis: Trotz sorgfältiger inhaltlicher Kontrolle übernehme ich keine Haftung für die Inhalte externer Links. Für die Inhalte der verlinkten Seiten sind ausschließlich deren Betreiber verantwortlich.

Kontakt und soziale Netzwerke

© 2019-2021 by Thomas Sillmann