0

I have one user who reports that the Open and Save panels have been "auto dismissing". ie the Open Panel dialog appears then immediately dismisses itself, taking the "cancel" path through the code

The file Open menu item is the standard firstResponder openDocument IBAction in the Storyboard

There is an IBAction openDocument routine in the AppDelegate which posts a notification which is observed by the main ViewController and which creates the NSOpenPanel and displays it with RunModal

class AppDelegate: NSObject, NSApplicationDelegate {
// standard AppDelegate routines omitted for brevity

   @IBAction func openDocument(_ sender: NSMenuItem) {
         let nc = NotificationCenter.default
         nc.post(Notification(name: Notification.Name("documentOpenRequested"), object: object))        
   }
}

class ViewController: NSViewController {


 override func viewDidLoad() {
       super.viewDidLoad()

        NotificationCenter.default.addObserver(self, selector: #selector(doOpenDocument), name: Notification.Name("documentOpenRequested"), object: nil)
   }

@objc func doOpenDocument(_ notification: Notification) {
        print ("doOpenDocument called on MainThread: \(Thread.current.isMainThread)")
        var URLToOpen: URL?
        if let selectedURL = notification.object as? URL {
           URLToOpen = selectedURL
       } else {
           let openPanel = NSOpenPanel();
           openPanel.allowsMultipleSelection = false;
           openPanel.canChooseDirectories = false;
           openPanel.canCreateDirectories = false;
           openPanel.canChooseFiles = true;
           openPanel.allowedFileTypes = ["sdf", "json", "txt"]
           openPanel.allowsOtherFileTypes = true
           let i = openPanel.runModal();
           if i.rawValue == NSApplication.ModalResponse.OK.rawValue  {
               if let myURL = openPanel.url {
                   URLToOpen = myURL
                   NSDocumentController.shared.noteNewRecentDocumentURL(myURL)
               }
           } else {
                print ("RunModal exited with response not OK")
           }
       }
       guard let theURL = URLToOpen else {
           // URL was bad or user aborted open request, either way just bail
           return
       }
}

The expected behaviour is that the RunModal displays the OpenDialog and waits for the user to select file and hit OK or Cancel, and that is what I get on my machine.

However on this one user's machine (MacBook Pro 13" M1 2020 running 11.4 ), the RunModal immediately exits taking the path which would print "RunModal exited with response not OK". Therefore the user is unable to choose a file

I did read some things which suggested doing an NSOpenPanel on other than the main queue could cause crashing. Willeke's reference suggests that notifications in this case would be posted on the main queue. I updated the sample to print whether the queue was the main queue and on my system it prints

doOpenDocument called on MainThread: true

So sticking the NSOpenPanel in a

       DispatchQueue.main.async {

          let openPanel = ...
       }

would not seem to solve the problem.

I don't have access to the specific machine which can replicate the error, making further debugging difficult. The "auto cancel" behaviour appears limited to this one user's machine but the config is common enough that I suspect I would be getting other reports even if it was limited to that specific config with M1 chip etc

Can anyone replicate this behaviour on this or other machines or run into any other reason for this "auto cancel" happening? (system setting, virus checker, etc)?

(Question updated to give expected behaviour and behaviour occurring, further debugging info, code info request by others and suggestions)

greg
  • 309
  • 1
  • 7
  • Nobody can tell what the issue is since you don't tell how you manage notification observers. I don't even know under what class you are writing code. It seems to me that you have a missing closing curly bracket. – El Tomato Nov 20 '21 at 23:16
  • Not quite sure what you mean by manage notification observers, I showed the AddObserver which is in viewDidLoad of the ViewController. I've edited to show that and that the doOpenDocument was meant to show the relevant snippet. I know the doOpenDocument is being triggered because the save panel is appearing and it works on other machines. – greg Nov 21 '21 at 00:52
  • "I showed the AddObserver which is in viewDidLoad of the ViewController" Initially, you didn't. – El Tomato Nov 21 '21 at 07:23
  • From where, when and how do you post the notification? Is the observer still around? – Willeke Nov 21 '21 at 09:25
  • 1
    Does this answer your question? [Is NSNotificationCenter thread safe?](https://stackoverflow.com/questions/15968430/is-nsnotificationcenter-thread-safe) – Willeke Nov 21 '21 at 09:25
  • I edited question to flesh out how the notification is posted (Storyboard link in open menu links to openDocument routine which posts in AppDelegate). Also, Willeke's documentation suggestion on NSNotification center suggests notification is posted in queue it originates from. I added debugging info to verify – greg Nov 21 '21 at 18:38

1 Answers1

0

I can replicate this behavior on M1 iMac with OS X 12.3.1 & Xcode 13.3.1 in SwiftUI based utility for MacOS X 12.3.

The issue has not yet been corrected. Other developers have suggested I switch to FileDocument & DocumentGroup protocols instead. No-one can explain this unusual behavior of NSOpenPanel immediately cancelling when called within a SwiftUI View.

Billy G.
  • 1
  • 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](/help/how-to-answer). – Community Apr 23 '22 at 19:07