I have a user who sent me the following crash report which occurs when SaveAsDialog.ShowModalWith is called. He says the app also crashes for him when he’s trying to open files from the File menu, while drag-and-drop of files works no problem. Here’s an edited crash log that occurs while trying to save a file from my app:
Has anyone else seen this kind of issue? I’ve never seen a crash log with EXC_BREAKPOINT in it before. Could there be old system files on this user’s machine that could cause this?
I’m using Xojo 2023r3 and the code editor seems to show ShowModalWithin as deprecated, (displays ShowModalWithin > ShowModal) and the docs doesn’t list ShowModalWithin. Should I not be using ShowModalWithin in my apps?
Crashes with open/save dialogs can happen when some plist files are corrupted.
If you go in “~/Library/Preferences” (i.e. the one inside the user’s folder), you may see files named like your app’s bundle with a plist extension (e.g. com.mycompany.myappname.plist), where the app name may eventually be localised.
If you open one, you can see a content similar to this:
(here, I’m just showing you that these files store information about open and save dialogs; those may become corrupted (rarely, but I’ve seen it happening)).
Trashing (or renaming/moving) the file corresponding to your application may recover the app in such cases.
When implementing these dialogs it is important to think like a Mac developer, not a Xojo developer. Xojo try to massage the Apple dialogs to work like they did decades ago, but modern macOS apps work differently.
You typically call these dialogs and give it the function (or block) to call when the user clicks on “Save” or “Open”.
My user came back to me. He tried deleting the prefs file that macOS generates as well as the one my app creates that stores the location of the parent folder of the last open/save which I use to set OpenDialog.InitialDirectory. He then restated the mac and tested again getting the same result. He sent an identical crash log below where OpenDialog.ShowModalWithin is called rather than SaveAsDialog.ShowModalWith as per the first crash report.
He also confirmed that the app crashes before the OpenDialog/SaveAsDialog window is shown. So @Sam_Rowlands, thanks for your input, but I’m not getting as far as this.
The only thing I can think to try is call ShowModal instead of ShowModalWithin. Possibly send the user a quick test app. This is a macOS Intel/ARM-64 and Windows Intel 64 app that works fine for 1000+ users, so not keen on creating special save/load dialogs for the mac build.
I created a test app with Xojo 2023r3 containing the following method:
Private Sub OpenFile(ShowWithin As Boolean)
Dim DefaultDestFolder as folderItem = SpecialFolder.Documents
Dim dlg as new openDialog
dlg.title = "Import AAF"
dlg.PromptText = "Select an AAF (.aaf) file to Import"
dlg.filter = FileTypes.AAF
dlg.InitialDirectory = DefaultDestFolder
Dim f As FolderItem
if ShowWithin then
f = dlg.ShowModalWithin(App.wMain)
else
f = dlg.ShowModal
end if
if f <> nil then
Msgbox("Load AAF " + f.Name)
else
Msgbox("User cancel")
end if
End Sub
I call this from 2x File menu items - one passing True and the other False. I also added 2x pushbuttons passing the same.
My client tested this app on his system and reports that all 4x ways of calling this method causes the app to crash before the open dialog is shown.
Here’s the crash report of the method called from the File menu passing False for ShowWithin:
I’ve been searching the net for info on how to interpret these results but can’t find anything. Does the absence of com.apple.quarantine from the client result mean the app is in quarantine? If so, I’m assuming he didn’t press okay on a macOS security message. Sorry this is all new to me. Does he need to run a xattr command to fix this?
I’ll also look at your second suggestion, especially as I have a test app that failed I can easily add this.
Try removing the part where you set InitialDirectory. Aside from all the issues it causes with permissions and dialogs, the system will restore the previously selected directory for you.
Is your application Sandboxed? If so, have you added the entitlements to allow folder item dialogs.
This crash is occurring within the Xojo framework. I would bring it up with Xojo. I’d also recommend trying a different version of Xojo incase this is a Xojo bug.
Notes:
Use the macOS preferences system, there is the ability to store a NSURL or URL in Swift, this will simplify matters and you’ll be following Apple’s guidelines on preferences.
Secondly, make sure that path is valid before passing it to the folderitem dialog, it could be that somewhere in Xojo’s conversion to NSURL is failing and they’re not checking it.
Lastly, and one I would advise from experience, is to remove the Xojo folderitem dialog on the Mac and use the code that Greg shared. While I’ve not tested his code, my last Xojo made apps all used alternative code for the NSOpen/NSSavePanels because of issues with Xojo’s I’d run into over the decades.
Thanks Greg. Initial testing is looking good. I have one update and question:
It looks to me like the following is required to avoid a NilObjectException if the user clicks ‘Cancel’ from the dialog when you only setup the first delegate (obj.Callback_ItemsSelected = AddressOf NSSavePanel_ItemsSelected):
Private Sub Response(value as integer)
#If TargetMacOS
If mDelegateCache <> nil Then // Required when user presses cancel
If mDelegateCache.HasKey(mPtr) Then
mDelegateCache.Remove(mPtr)
End If
End if
...
End Sub
Is there a reason there is no NSSavePanelGTO.ShowModalWithin method? Would it be possible to add this?
After sending my client several test apps it turns out SpecialFolder.Documents returns Folderitem.Exists = False on his system. Assigning this to either the Xojo OpenDialog.InitialDirectory or OpenFileDialog.InitialFolder causes the app to crash as per the crash logs above. I can simply check this folder is not nil and exists to fix the issue (in my main apps my prefs store the last parent folder that was used by a particular Open/Save-As dialog and defaults to SpecialFolder.Documents when first used).
Regarding the crash with Xojo OpenDialog.InitialDirectory and OpenFileDialog.InitialFolder, I tried assigning a folderitem that was nil or Exists = False, but couldn’t replicate the crash, the dialogs seem to just ignore it. So I’m not sure what’s so special about my clients Documents folder.
I also added the MBS OpenDialogMBS dialog and Greg O’s Mac Declares to my test apps. My client reported that when his Documents folder was passed to either, the app didn’t crash. Presumably they both have built-in checks.