Beginning with iOS 16, SwiftUI introduces a local picture picker view referred to as PhotosPicker
. In case your app requires entry to customers’ picture library, the PhotosPicker view seamlessly manages the picture choice course of. This built-in view affords outstanding simplicity, permitting builders to current the picker and deal with picture choice with only a few strains of code.
When presenting the PhotosPicker
view, it showcases the picture album in a separate sheet, rendered atop your app’s interface. In earlier variations of iOS, you couldn’t customise or change the looks of the photographs picker view to align along with your app’s format. Nevertheless, Apple has launched enhancements to the PhotosPicker view in iOS 17, enabling builders to seamlessly embed it inline throughout the app. Moreover, you could have the choice to change its measurement and format utilizing normal SwiftUI modifiers akin to .body
and .padding
.
On this tutorial, I’ll present you how you can implement an inline picture picker with the improved PhotosPicker
view.
Revisiting Photograph Pickers
To make use of the PhotosPicker
view, you possibly can first declare a state variable to retailer the picture choice after which instantiate a PhotosPicker
view by passing the binding to the state variable. Right here is an instance:
struct ContentView: View {
@State personal var selectedItem: PhotosPickerItem?
var physique: some View {
PhotosPicker(choice: $selectedItem,
matching: .pictures) {
Label(“Choose a photograph”, systemImage: “picture”)
}
}
}
import SwiftUI import PhotosUI Â struct ContentView: View { Â Â Â Â Â @State personal var selectedItem: PhotosPickerItem? Â Â Â Â Â var physique: some View { Â Â Â Â Â Â Â Â PhotosPicker(choice: $selectedItem, Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â matching: .pictures) { Â Â Â Â Â Â Â Â Â Â Â Â Label(“Choose a photograph”, systemImage: “picture”) Â Â Â Â Â Â Â Â } Â Â Â Â } } |
The matching
parameter means that you can specify the asset kind to show. Right here, we simply select to show pictures solely. Within the closure, we create a easy button with the Label
view.
Upon deciding on a photograph, the picture picker robotically dismisses itself, and the chosen picture merchandise is saved within the selectedItem
 variable, which is of kind PhotosPickerItem
. To load the picture from the merchandise, you should utilize loadTransferable(kind:completionHandler:)
. You may connect the onChange
 modifier to hearken to the replace of the selectedItem
variable. At any time when there’s a change, you name the loadTransferable
 technique to load the asset knowledge like this:
.
.
.
.onChange(of: selectedItem) { oldItem, newItem in
Job {
if let picture = strive? await newItem?.loadTransferable(kind: Picture.self) {
selectedImage = picture
}
}
}
@State personal var selectedImage: Picture?  . . .  .onChange(of: selectedItem) { oldItem, newItem in     Job {         if let picture = strive? await newItem?.loadTransferable(kind: Picture.self) {             selectedImage = picture         }     } } |
When utilizing loadTransferable
, it’s essential to specify the asset kind for retrieval. On this case, we make use of the Picture
 kind to straight load the picture. If the operation is profitable, the strategy will return an Picture
 view, which can be utilized to straight render the picture on the display screen.
if let selectedImage {     selectedImage         .resizable()         .scaledToFit()         .padding(.horizontal, 10) } |
Implementing an Inline PhotosPicker
Now that it’s best to perceive how you can work with a PhotosPicker
, let’s see how you can embed it in our demo app. What we’re going to do is to switch the “Choose a photograph” button with an inline Photographs picker. The up to date model of PhotosPicker
comes with a brand new modifier known as photosPickerStyle
. By specify a worth of .inline
, the Photographs picker will probably be robotically embedded within the app:
.photosPickerStyle(.inline) |
You can too connect normal modifiers like .body
and .padding
to regulate the dimensions of the picker.
By default, the highest accent of the picker is the navigation bar and the underside accent is the toolbar. To disable each bars, you possibly can apply the photosPickerAccessoryVisibility
modifier:
.photosPickerAccessoryVisibility(.hidden) |
Optionally, you possibly can conceal both of them:
.photosPickerAccessoryVisibility(.hidden, edges: .backside) |
Dealing with A number of Photograph Picks
Presently, the Photographs picker solely permits customers to pick out a single picture. To allow a number of picks, you possibly can decide within the steady choice conduct by setting the selectionBehavior
to .steady
or .continuousAndOrdered
:
PhotosPicker(choice: $selectedItems, Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â maxSelectionCount: 5, Â Â Â Â Â Â Â Â Â Â Â Â selectionBehavior: .continuousAndOrdered, Â Â Â Â Â Â Â Â Â Â Â Â matching: .pictures) { Â Â Â Â Label(“Choose a photograph”, systemImage: “picture”) } |
If you happen to want to limit the variety of gadgets accessible for choice, you possibly can specify the utmost rely utilizing the maxSelectionCount
 parameter.
As soon as the consumer has chosen a set of photographs, they’re saved within the selectedItems
 array. The selectedItems
 array has been modified to accommodate a number of gadgets and is now of kind PhotosPickerItem
.
@State personal var selectedItems: [PhotosPickerItem] = [] |
To load the chosen photographs, you possibly can replace the onChange
closure like this:
selectedImages.removeAll()
newItems.forEach { newItem in
Job {
if let picture = strive? await newItem.loadTransferable(kind: Picture.self) {
selectedImages.append(picture)
}
}
}
}
.onChange(of: selectedItems) { oldItems, newItems in      selectedImages.removeAll()      newItems.forEach { newItem in          Job {             if let picture = strive? await newItem.loadTransferable(kind: Picture.self) {                 selectedImages.append(picture)             }         }      } } |
I used an Picture
array to retailer the retrieved pictures.
@State personal var selectedImages: [Image] = [] |
To show the chosen pictures, chances are you’ll use a horizontal scroll view. Right here is the pattern code that may be positioned firstly of the VStack
view:
ScrollView(.horizontal) {
LazyHStack {
ForEach(0..<selectedImages.rely, id: .self) { index in
selectedImages[index]
.resizable()
.scaledToFill()
.body(peak: 250)
.clipShape(RoundedRectangle(cornerRadius: 25.0))
.padding(.horizontal, 20)
.containerRelativeFrame(.horizontal)
}
}
}
.body(peak: 300)
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
if selectedImages.isEmpty {     ContentUnavailableView(“No Photographs”, systemImage: “picture.on.rectangle”, description: Textual content(“To get began, choose some photographs under”))         .body(peak: 300) } else {      ScrollView(.horizontal) {         LazyHStack {             ForEach(0..<selectedImages.rely, id: .self) { index in                 selectedImages[index]                     .resizable()                     .scaledToFill()                     .body(peak: 250)                     .clipShape(RoundedRectangle(cornerRadius: 25.0))                     .padding(.horizontal, 20)                     .containerRelativeFrame(.horizontal)             }          }     }     .body(peak: 300) } |
If you happen to’d prefer to study extra about how you can create picture carousels, you possibly can take a look at this tutorial. In iOS 17, a brand new view known as ContentUnavailableView
 is launched. This view is really useful to be used in situations the place the content material of a view can’t be displayed. So, when no picture is chosen, we use the ContentUnavailableView
 to current a concise and informative message.
Abstract
In iOS 17, Apple made enhancements to the native Photographs picker. Now, you possibly can simply embody it inside your app as a substitute of utilizing a separate sheet. This tutorial explains the brand new modifiers that include the up to date PhotosPicker
view and exhibits you how you can create an inline picture picker.
If you happen to take pleasure in studying this tutorial and need to dive deeper into SwiftUI, you possibly can take a look at our Mastering SwiftUI e-book.