13

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.

Michel
  • 10,303
  • 17
  • 82
  • 179

2 Answers2

17

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()
    }
}
aheze
  • 24,434
  • 8
  • 68
  • 125
  • 1
    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. – Michel Apr 21 '21 at 03:36
  • @Michel 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) – aheze Apr 21 '21 at 14:28
  • 1
    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: https://stackoverflow.com/questions/67189413/handling-a-list-of-buttons-in-swiftui – Michel Apr 21 '21 at 14:39
7

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.

Big_Chair
  • 2,781
  • 3
  • 31
  • 58