1

I'm building a macOS SwiftUI app. In it, I have a popover with a TextField. The TextField has a binding that updates an ObservableObject that then propagates its value back down a NavigationView to the Detail View.

On the first keyboard entry to the TextField, the popover closes. However, on all subsequent entries, the popover stays open.

I've also tried this with a DatePicker and have had the same results, so it's not limited to the TextField entry.

Note that this does not happen when running the same code on iOS (on iPhone where popovers are displayed as sheets or on iPad where they are popovers).

I've included a minimal example.

Anyone have any clue how to avoid the popover closing on first edit?

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

    var window: NSWindow!

    func applicationDidFinishLaunching(_ aNotification: Notification) {
        let contentView = ContentView(store: AppState())

        window = NSWindow(
            contentRect: NSRect(x: 0, y: 0, width: 480, height: 300),
            styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
            backing: .buffered, defer: false)
        window.center()
        window.setFrameAutosaveName("Main Window")
        window.contentView = NSHostingView(rootView: contentView)
        window.makeKeyAndOrderFront(nil)
    }

}

class AppState : ObservableObject {
    @Published var models : [String:Model] = ["1" : Model(id: "1", title: "June 14"),
                                              "2" : Model(id: "2", title: "July 21"),
                                              "3" : Model(id: "3", title: "Sept 5")]
    
    func changeTitle(key: String, newTitle: String) {
        guard var model = self.models[key] else {
            return
        }
        model.title = newTitle
        self.models[key] = model
    }
}

struct Model {
    var id : String
    var title: String
}


struct ContentView: View {
    @ObservedObject var store : AppState
    
    var body: some View {
        NavigationView {
            VStack {
                List {
                    ForEach(Array(store.models.values), id: \.id) { model in
                        NavigationLink(destination: DetailView(model: model,
                                                           changeTitle: { title in
                                                                self.store.changeTitle(key: model.id, newTitle: title)
                        })) {
                            VStack(alignment: .leading) {
                                Text(model.title).font(.headline)
                            }.padding(.vertical, 8)
                        }
                    }
                }.frame(minWidth: 150, idealWidth: 200, maxWidth: 200, maxHeight: .infinity)
            }
            
            EmptyView()
                .frame(maxWidth: .infinity, maxHeight: .infinity)
        }
    }
}

struct DetailView : View {
    var model : Model
    var changeTitle: (String) -> Void
    
    @State private var showPopover = false
    
    var customBinding : Binding<String> {
        Binding<String>(get: { self.model.title }, set: { newValue in
            self.changeTitle(newValue)
        })
    }
    
    var body: some View {
        VStack {
            Text(model.title)
            Button("Edit") {
                self.showPopover.toggle()
            }.popover(isPresented: self.$showPopover) {
                TextField("Text", text: self.customBinding)
                    .frame(minWidth: 300)
                .padding()
            }
        }
            .frame(maxWidth: .infinity, maxHeight: .infinity)
    }
}
2
  • Catalina? It works as expected on Big Sur. Commented Aug 11, 2020 at 9:41
  • Yes, Catalina -- 10.15.3 and 10.15.6 tested. I guess it's comforting that it works on Big Sur. Commented Aug 11, 2020 at 15:09

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.