SwiftUI Photo Picker App with PhotosUI
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
- Open Xcode and create a new SwiftUI project.
- Name your project (e.g., “PhotoPickerApp”).
- 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.
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.