SwiftUI [Presentation] / Attempt to present View on ... which is already presenting
Asked Answered
F

4

25

I am working on a SwiftUI app and am having warnings first and later bugs, probably because I ignored the warnings. I want to show the warnings I am getting and I hope somebody can point out something I may be doing wrong.

Here is the relevant code:

struct CustomListView: View {
    var localList:[SomeManagedObject], moc:NSManagedObjectContext
    @State var showingOtherView = false
    
    func handleCustomItem(_ argument: SomeManagedObject) {
        print(#function)
        self.showingOtherView.toggle()
        ..... Do useful things .....
    }
    
    var body: some View {
        List {
            ForEach(self.localList) {
                item in
                HStack {
                    Spacer()
                    Button(action: {
                        self.handleCustomItem(item)
                    })
                    {
                        Text(item.expression!)
                            .foregroundColor(Color.red))
                            .font(.headline)
                            .padding(.horizontal, 11).padding(.vertical, 15)
                    }.sheet(isPresented: $showingOtherView) {
                        OtherView()
                    }
                    Spacer()
                }
            }
        }
    }
}

This is the code for OtherView:

import SwiftUI
import CoreData

struct OtherView: View {

    var body: some View {
        Text("Hello OtherView")
    }
}

And these are the messages I can see in the debugging console, when I click one button in the list and execute the handleCustomItem() function :

handleCustomItem(_:) 2021-04-20 22:53:10.667895+0900 TheApp[9600:5758072] [Presentation] Attempt to present <TtGC7SwiftUI29PresentationHostingControllerVS_7AnyView: 0x10529a510> on <TtGC7SwiftUI29PresentationHostingControllerVS_7AnyView: 0x10510a310> (from <TtGC7SwiftUI29PresentationHostingControllerVS_7AnyView: 0x10510a310>) which is already presenting <TtGC7SwiftUI29PresentationHostingControllerVS_7AnyView: 0x105299150>. 2021-04-20 22:53:10.668399+0900 TheApp[9600:5758072] [Presentation] Attempt to present <TtGC7SwiftUI29PresentationHostingControllerVS_7AnyView: 0x10529b1b0> on <TtGC7SwiftUI29PresentationHostingControllerVS_7AnyView: 0x10510a310> (from <TtGC7SwiftUI29PresentationHostingControllerVS_7AnyView: 0x10510a310>) which is already presenting <TtGC7SwiftUI29PresentationHostingControllerVS_7AnyView: 0x105299150>. ........... 2021-04-20 22:53:10.670049+0900 TheApp[9600:5758072] [Presentation] Attempt to present <TtGC7SwiftUI29PresentationHostingControllerVS_7AnyView: 0x105118e10> on <TtGC7SwiftUI29PresentationHostingControllerVS_7AnyView: 0x10510a310> (from <TtGC7SwiftUI29PresentationHostingControllerVS_7AnyView: 0x10510a310>) which is already presenting <TtGC7SwiftUI29PresentationHostingControllerVS_7AnyView: 0x105299150>.

That would be great if one could see something and give me a hint on what I can do.

Flour answered 20/4, 2021 at 14:31 Comment(0)
C
24

Your .sheet(isPresented: $showingOtherView) { is inside the ForEach. When you set showingOtherView to true, all the sheets in the ForEach will try to present. That's a looooot of sheets.

You want to put it outside the ForEach.

var body: some View {
    List {
        ForEach(self.localList) {
            item in
            HStack {
                Spacer()
                Button(action: {
                    self.handleCustomItem(item)
                })
                {
                    Text(item.expression!)
                        .foregroundColor(Color.red))
                    .font(.headline)
                    .padding(.horizontal, 11).padding(.vertical, 15)
                }
                Spacer()
            }
        }
    }
    .sheet(isPresented: $showingOtherView) { /// here should be fine
        OtherView()
    }
}
Capone answered 20/4, 2021 at 15:24 Comment(3)
When I first tried to think the way you mention, I found that the number of messages was not always matching the number of lines in the list, so I kind of concluded it was the wrong approach. But trying what you suggest works, so you must be right. And I was certainly missing some detail.Flour
@Flour SwiftUI Lists load lazily, so the number of messages should be close to the number of rows currently on the screen, minus 1 (the first sheet will present no problem, but every sheet after that will have an error message)Capone
This is what I expected, but it does not seem to be that way. At least not always. Or maybe there is a message for each visible cell, but I haven't checked that. Anyway the error messages are now gone, this is good. But now I have another problem, I can't pass information from a cell to OtherView. I have actually created another post for that: #67189913Flour
C
9

I had the same warning message/bug, but my reason was not too many sheets as in your case. It was that I tried to present one sheet after the other too fast like this:

naviViewModel.isSUModalPresented = false
naviViewModel.isPaidContentIntroPresented = true

Which I had to change to:

naviViewModel.isSUModalPresented = false
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { // or even shorter
     naviViewModel.isPaidContentIntroPresented = true
}

And now it works perfectly. SwiftUI just needs a few milliseconds to finish the animations.

Chock answered 27/3, 2022 at 17:54 Comment(0)
T
3

I had the same error, but mine was solved by moving the .sheet on another object than the Section() element (I moved it on the ForEach instead)

Terpsichorean answered 11/4 at 9:44 Comment(1)
It works. In my case a section has only one button. I moved .sheet under the button inside that section and there are no warnings now. Thank you.Saltatory
D
-2

Put your code in a NavigationStack. Something like this:

var body: some View {
    NavigationStack {
        List {
            
        }
    }
}
Dysarthria answered 12/9, 2023 at 22:3 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Setting

© 2022 - 2024 — McMap. All rights reserved.