PhotosPicker in iOS 16 can be declared only with a separate trigger view. If this view is a part of regular view, then it’s OK. But if it’s declared in Menu as one of the options, then it doesn’t appear after triggering (Xcode 14 beta 5).
So, this works:
struct ContentView: View {
@State private var selectedPhotoItem: PhotosPickerItem?
var body: some View {
PhotosPicker(
selection: $selectedPhotoItem,
matching: .images,
photoLibrary: .shared()
) {
Image(systemName: "photo.on.rectangle.angled")
}
}
}
And this is not:
struct ContentView: View {
@State private var selectedPhotoItem: PhotosPickerItem?
var body: some View {
Menu {
PhotosPicker(
selection: $selectedPhotoItem,
matching: .images,
photoLibrary: .shared()
) {
Label("Photo Library", systemImage: "photo.on.rectangle.angled")
}
Button(“Another action”) { }
} label: {
Text("Menu")
}
}
}
The same behaviour we have for ‘toolbar’ in NavigationStack. If PhotosPicker declared directly in ToolbarItem, it’s OK. But if it’s inside Menu of ToolbarItem, then it doesn’t appear after triggering.
As I can guess PhotosPicker can’t appear for the same reason as the '.sheet' or '.alert' attached to Button inside Menu. It may be because of disappearing Menu after picking an option.
This also won’t work:
struct ContentView: View {
@State private var isPresentedSheet = false
var body: some View {
Menu {
Button(“Some action”) { isPresentedSheet = true }
.sheet(isPresented: $isPresentedSheet) {
SomeView()
}
Button(“Another action”) { }
} label: {
Text("Menu")
}
}
}
struct SomeView: View {
var body: some View {
Text("Hello")
}
}
But in this case we can simply shift .sheet modifier up in the view hierarchy and it will work.
struct ContentView: View {
@State private var isPresentedSheet = false
var body: some View {
Menu {
Button(“Some action”) { isPresentedSheet = true }
Button(“Another action”) { }
} label: {
Text("Menu")
}
.sheet(isPresented: $isPresentedSheet) {
SomeView()
}
}
}
struct SomeView: View {
var body: some View {
Text("Hello")
}
}
However with PhotosPicker there is no possibility to trigger it outside the Menu anywhere else in ‘body’. It has no ‘isPresented’ parameter or something like that. So the only possibility to show PhotosPicker now is the explicit view, that you can press on the screen - not from Menu.
I have a design where PhotosPicker should be triggered from Menu of a Button. And I have no idea, how to show it right now.
Is it a bug? Or is it a fundamental limitation of SwiftUI presentation system?
Came here with the same issue but then also found a thread discussing a modifier for photosPicker similar to .sheet (https://developer.apple.com/forums/thread/713564)
.toolbar {
ToolbarItem(placement: .primaryAction) {
Menu {
Button {
showingPhotosPicker.toggle()
} label: {
Label("Add Photo", systemImage: "photo.on.rectangle")
}
} label: {
Label ("More", systemImage: "ellipsis.circle")
}
}
}
.photosPicker(isPresented: $showingPhotosPicker, selection: $selectedItems, matching: .any(of: [.images, .screenshots, .livePhotos]))
}