How to let users select pictures using PhotosPicker
How to let users select pictures using PhotosPicker 관련
Updated for Xcode 15
New in iOS 16
SwiftUI's PhotosPicker
brings up the system-standard photo import user interface, allowing users to select one or more images or videos to bring in to your app.
To use it to bring in an image, you need to import the PhotosUI
module, then create some storage for a PhotosPickerItem
to save what the user selected, and also an Image
property to store the loaded asset. You can then watch for the PhotosPickerItem
changing, and load its contents like this:
import PhotosUI
import SwiftUI
struct ContentView: View {
@State private var avatarItem: PhotosPickerItem?
@State private var avatarImage: Image?
var body: some View {
VStack {
PhotosPicker("Select avatar", selection: $avatarItem, matching: .images)
avatarImage?
.resizable()
.scaledToFit()
.frame(width: 300, height: 300)
}
.onChange(of: avatarItem) {
Task {
if let loaded = try? await avatarItem?.loadTransferable(type: Image.self) {
avatarImage = loaded
} else {
print("Failed")
}
}
}
}
}
If you want more control over the data that is selected, adjust the matching
parameter based on what you're looking for:
- Use
matching: .screenshots
if you only want screenshots. - Use
matching: .any(of: [.panoramas, .screenshots])
if you want either of those types. - Use
matching: .not(.videos)
if you want any media that isn't a video. - Use
matching: .any(of: [.images, .not(.screenshots)]))
if you want all kinds of images except screenshots.
If you want to let the user select multiple images, you should use an array of PhotosPickerItem
objects then load them individually using a similar process:
import PhotosUI
import SwiftUI
struct ContentView: View {
@State private var selectedItems = [PhotosPickerItem]()
@State private var selectedImages = [Image]()
var body: some View {
NavigationStack {
ScrollView {
LazyVStack {
ForEach(0..<selectedImages.count, id: \.self) { i in
selectedImages[i]
.resizable()
.scaledToFit()
.frame(width: 300, height: 300)
}
}
}
.toolbar {
PhotosPicker("Select images", selection: $selectedItems, matching: .images)
}
.onChange(of: selectedItems) {
Task {
selectedImages.removeAll()
for item in selectedItems {
if let image = try? await item.loadTransferable(type: Image.self) {
selectedImages.append(image)
}
}
}
}
}
}
}