0

OK, I'm not a SwiftUI expert. I am also not big on Swift. But I spent 20+ years coding in C and C++. So this "swift" UI thing is really puzzling. Can someone explain why this seemingly simple thing does not work.

Here's what I need to do: I have a macOS GUI app. When I click OK button in it I want to display a modal message box. Is it possible in Swift UI?

There's no function to do that, and one needs to use .alert for that.

So I did:

struct ContentView: View {
    
    @ObservedObject var gDVM = DataViewModel.shared
    
    var body: some View {
        
        NavigationView {

            MenuView(menuOptions: menuOptions,
                 curSelMenu: $currentMenu)
            
            ConfigView()

        }
        .alert(isPresented: $gDVM.gOKMsgBox.bShow) {
            //Show message box
            Alert(title: Text("Title"),
                  message: Text(gDVM.gOKMsgBox.strMsg)
            )
        }
   }
}

where:

class ModalOkMsgBoxInfo
{
    var bShow : Bool = false;
    var strMsg : String = ""
    
    func showOkMsgBox(msg : String)
    {
        strMsg = msg
        bShow = true
    }
}

class DataViewModel : ObservableObject
{
    static let shared = DataViewModel()
    
    @Published public var gOKMsgBox : ModalOkMsgBoxInfo
}

So when I want to display my message box:

struct ConfigView : View {
    
    @ObservedObject var gDVM = DataViewModel.shared
    
    var body : some View {

        //...

                Button(action: {
                    OK_proc()
                 }) {
                     Text("OK")
                 }
    }
}

func OK_proc() -> ()
{
    showOkMsgBox(msg: "Show a pop-up!")
}

func showOkMsgBox(msg : String)
{
    @ObservedObject var gDVM = DataViewModel.shared
    
    gDVM.gOKMsgBox.strMsg = msg
    gDVM.gOKMsgBox.bShow = true
}

First of all, why is it so complicated. But alright.

When I click my OK button and call my showOkMsgBox, nothing happens. And only when I click away into some other UI control, it shows my message box?

I spent an hour trying to figure it out.

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
c00000fd
  • 20,994
  • 29
  • 177
  • 400
  • The purpose of SwiftUI wrappers is to reload “body” they don’t belong inside functions becuase they don’t have a “body” – lorem ipsum Mar 28 '23 at 09:27
  • 1
    Also “ ModalOkMsgBoxInfo” should be a struct not a class. Value/reference. Putting a reference type inside of a reference type is much harder to observe they must all be ObservableObjects and must be individually wrapped in a View – lorem ipsum Mar 28 '23 at 09:30
  • Try the [Apple SwiftUI Tutorials](https://developer.apple.com/tutorials/swiftui) and watch Demystify SwiftUI they really will help you bridge the gap. – lorem ipsum Mar 28 '23 at 09:31
  • @loremipsum wow. Yes, changing it to `struct` made it work. Thanks. What's the magic there? – c00000fd Mar 28 '23 at 09:51

2 Answers2

1

The purpose of SwiftUI wrappers is to reload body they don’t belong inside functions because they don’t have a body.

Also ModalOkMsgBoxInfo should be a struct not a class. Value/reference. Putting a reference type inside of a reference type is much harder to observe they must all be ObservableObjects and must be individually wrapped in a View

Published emits changes when the “value” changes, changing a variable of a class doesn’t change the object’s value since the value is a way a memory reference. A struct is a value type so changing a variable is changing the value.

lorem ipsum
  • 21,175
  • 5
  • 24
  • 48
0

OK, found the answer. Instead of doing what I showed in my OP, just call the following to show a modal dialog:

func dialogOKCancel(question: String, text: String) -> Bool {
    let alert = NSAlert()
    alert.messageText = question
    alert.informativeText = text
    alert.alertStyle = .warning
    alert.addButton(withTitle: "OK")
    alert.addButton(withTitle: "More")
    alert.addButton(withTitle: "Cancel")
    return alert.runModal() == .alertFirstButtonReturn
}
c00000fd
  • 20,994
  • 29
  • 177
  • 400