PhotosPicker doesn’t appear when declared inside Menu

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?

Answered by MSans in 737831022

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]))

    }

        

I ran into the same issue. It's still the case for Xcode 14 beta 6 and iOS 16 beta 8 devices. :(

The same issue using Xcode 14.0 (14A309).

I can confirm the same issue on both Xcode 14.0 and 14.1 Beta (14B5033e). I've submitted a feedback (FB11699869) for this, hopefully they'll fix it.

Accepted Answer

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]))

    }

        
11

Hello this is a way that it works for me but in an overlay for a RoundedRectangle.

Menu {

    Button("Photo Library", action:  {

        

        self.sheetForPL.toggle()

    })

    Button("Camera", action:  {
        print("Camera has been choosen")
    })

} label: {
    Image(systemName: "plus.circle.fill")

        .symbolRenderingMode(.hierarchical)

        .foregroundColor(.white)

}



.photosPicker(isPresented: $sheetForPL, selection: $imagePicker.imageSelection)
PhotosPicker doesn’t appear when declared inside Menu
 
 
Q