SwiftUI Photo Picker App with PhotosUI

Rizal Hilman
3 min readMay 27, 2024

--

Photos Picker App on Simulator

SwiftUI and PhotosUI provide powerful tools for creating rich and interactive user interfaces in iOS apps. In this tutorial, we will build an app that allows users to select photos from their photo library and display them.

Setting Up Your Project

  1. Open Xcode and create a new SwiftUI project.
  2. Name your project (e.g., “PhotoPickerApp”).
  3. Ensure you select SwiftUI as the user interface and Swift as the programming language.

Code Explanation

Step 1: Import Necessary Frameworks

import SwiftUI
import PhotosUI
  • SwiftUI: Framework for building user interfaces.
  • PhotosUI: Framework for photo and video selection and management.

Step 2: Define State Variables

struct ContentView: View {
@State private var selectedPhotos: [PhotosPickerItem] = []
@State private var images: [UIImage] = []
@State private var errorMessage: String?

// ... the rest of code

}
  • selectedPhotos: Stores selected photo items.
  • images: Stores loaded images.
  • errorMessage: Stores any error messages.

Step 3: Create the Main View

var body: some View {
VStack {
Form {
photoPickerSection
imagesSection
}
if let errorMessage = errorMessage {
Text(errorMessage)
.foregroundColor(.red)
.padding()
}
}
}
  • VStack: Contains the form and error message.
  • Form: Contains sections for the photo picker and images.

Step 4: Define the Photo Picker Section

private var photoPickerSection: some View {
Section {
PhotosPicker(selection: $selectedPhotos, maxSelectionCount: 3, matching: .images) {
Label("Select a photo", systemImage: "photo")
}
.onChange(of: selectedPhotos) { _ in
loadSelectedPhotos()
}
}
}
  • PhotosPicker: UI component for selecting photos.
  • selection: Binds to `selectedPhotos`.
  • maxSelectionCount: Limits selection to 3 photos.
  • matching: Restricts selection to images.
  • .onChange: Calls `loadSelectedPhotos` when `selectedPhotos` changes.

Step 5: Define the Images Section

private var imagesSection: some View {
Section {
ForEach(images, id: \.self) { image in
Image(uiImage: image)
.resizable()
.scaledToFit()
.frame(maxWidth: .infinity)
.clipShape(RoundedRectangle(cornerRadius: 10.0))
.padding(.vertical, 10)
}
}
}
  • ForEach: Iterates over `images` array.
  • Image(uiImage:): Displays each image.
  • .resizable(), .scaledToFit(), .frame(maxWidth: .infinity), .clipShape(), .padding(): Styles the images.

Step 6: Load Selected Photos

private func loadSelectedPhotos() {
images.removeAll()
errorMessage = nil

Task {
await withTaskGroup(of: (UIImage?, Error?).self) { taskGroup in
for photoItem in selectedPhotos {
taskGroup.addTask {
do {
if let imageData = try await photoItem.loadTransferable(type: Data.self),
let image = UIImage(data: imageData) {
return (image, nil)
}
return (nil, nil)
} catch {
return (nil, error)
}
}
}

for await result in taskGroup {
if let error = result.1 {
errorMessage = "Failed to load one or more images."
break
} else if let image = result.0 {
images.append(image)
}
}
}
}
}
  • images.removeAll(): Clears existing images.
  • errorMessage = nil: Resets error message.
  • Task: Initiates an asynchronous task.
  • withTaskGroup: Manages concurrent tasks to load photos.
  • photoItem.loadTransferable(type: Data.self): Loads photo data.
  • UIImage(data: imageData): Converts data to `UIImage`.
  • errorMessage: Updates on error.
  • images.append(image): Adds loaded images to the array.

Step 7: Preview the View

#Preview {
ContentView()
}
  • #Preview: Allows you to preview the `ContentView` in Xcode’s canvas.

Run the project

Now run the project to the simulator or real devices.

PhotosPicker PhotoUI app running in iPhone Simulator

Summary

This tutorial has guided you through building a SwiftUI app that allows users to select and display photos. We’ve covered state management, asynchronous tasks, and image handling. This app can be expanded with additional features such as photo editing, saving, or sharing. Experiment with SwiftUI and PhotosUI to enhance your app’s functionality and user experience.

Happy coding!

Complete Code

Clone / download this repo to see the complete code.

--

--

Rizal Hilman

Tech Mentor at Apple Developer Academy - Batam | Apple Swift Certified Trainer | Apple Professional Learning Specialist | Apple Teacher | WWDC19 Winner