SpecialFolders on a Mac query

I am working on a Mac and have been using the SpecialFolder “Documents” to store folders with files of data I need to read from and write to but I am always getting the alert “myapp.debug.app” would like to access files in your Documents folder.

Is there a folder I. can use where I don’t get this message?

Data and documents for your app to function you can safely store in a child of SpecialFolder.ApplicationData usually a folder that’s your bundle identifier.

var fData as FolderItem = SpecialFolder.ApplicationData.Child("com.mywebsite.myapp")
if not fData.Exists then
  fData.CreateFolder

end

// Your individual files and stuff go inside fData

If it’s a document you need your user to interact with (like a save file) you need to access these with Open / Save dialogs.

[quote=“Tim Parnell, post:2, topic:70743, username:Tim_Parnell”]

var fData as FolderItem = SpecialFolder.ApplicationData.Child("com.mywebsite.myapp")
if not fData.Exists then
  fData.CreateFolder

end
Thanks Tim. I'm a bit puzzled though. I read that ApplicationData was a Special Folder, but when I tried to search for it on my Mac so I could drag my data folders across, nothing came up.

So Ok, I used your suggestion.
var fData as FolderItem = SpecialFolder.ApplicationData
if not fData.Exists then
  fData.CreateFolder

and searched again, but I still couldn't find the ApplicationData folder although stepping through the code, it seemed that it did exist

So I thought maybe it wasn't visible and tried making it visible in code, but that didn't work either. Am I missing something here? I just want to put some named folders in the ApplicationData folder by dragging them across with my data files in them, and then access my data programatically.

Sorry if I am being stupid here.

I’m sorry I haven’t quite got to grips with the display features on this forum so some of my last post may not be readable but I think you will get the gist. I can’t find the ApplicationData folder by searching in the same that I can find the Documents folder.

SpecialFolder.ApplicationData is ~/Library/Application Support/ and you generally make your own subfolder in there.

However, if these are data files that your user regularly needs to put in and out of your program, you need to ask for the files with a Open dialog and save them back out with a Save dialog. That’s just how macOS is meant to operate.

Check the docs for SpecialFolder to see where each one points to on each platform.

Open a Finder window
Click the Go menu
image

Pres the ALT key, and ‘Library’ will appear in the menu

image

ApplicationSupport is there:

image

Unless your user does the same manually, you might need to include a way to ‘Launch’ that folder from within your app, which will make Finder open a window showing the contents.

As an alternative, you can also check fData’s NativePath in the debugger (or by showing a MessageDialog/whatever) to discover the path.

ApplicationData is meant to already exist on most, if not all, Mac OS installations (upon installation). The subfolders and subfiles are the ones you should attempt to create the first time.

Thanks for all the pointers, I didn’t realise I had to tell the Mac where the special folder ApplicationSupport was since I didn’t have to do that with the special folder Documents. Specifying the address solved it:

dim d as new FolderItem("/Users/myimac/Library/Application Support")

You totally do not have to do that.
Specialfolder.applicationdata is what you need.

So I thought maybe it wasn’t visible and tried making it visible in code

It IS normally invisible.
Just because you cant immediately see it doesn’t mean it isn’t there.

dim d as FolderItem
d = Specialfolder.applicationdata

is the right approach, and will work if Apple change things in the future.
Especially if myImac gets renamed somewhow… :wink:

More specifically, the parent folder (“Library”) is hidden by default on Mac OS X. The “Application support” itself is visible.

Unless if the change is about removing the “Application support” folder.

I thought this problem was done and dusted but have been tearing my hair over it all day. After shifting my external text files to Application Support, I found I couldn’t get textinputstream to work, so I couldn’t load the data. My Mac had suddenly decided that although it could locate the files - so my path was valid - the files apparently didn’t exist.

Eventually, I decided that I might as well put them all back in the Documents folder and put up with the popup alert window warning me that I was trying to access my files. Unfortunately, that didn’t solve the problem, I did get the alert window again but I could no longer load the files from the Documents folder as I had been doing quite successfully before. The folderitems are not Nil, but the last one, with the name of the file, does not exist

The one possible problem I could think of was that I had given in to Apple nagging and updated my OS to 10.15.7 (I am working on my elderly iMac).

When I looked at the files again, all of which have been created or at least edited in TextEdit, I found the “Open With” field in the information window was set to TextEdit (I assume it always has been). I changed this to the only application that might work, which is Xojo, but that doesn’t solve the problem because the Mac presumably thinks the “myapp.debug.app” I am running my program in is not Xojo.

So I now seem to be well and truly stymied with the development :frowning:

the “myapp.debug.app” I am running my program in is not Xojo.

True.
And the thing you changed would only have made MacOS open Xojo if you double clicked the file.
It has no impact on how TextInputStream works. (It is INPUTstream, not OUTPUTSTream, yes?)

After shifting my external text files to Application Support,

By what method did you put the files there?

My Mac had suddenly decided that although it could locate the files - so my path was valid

What test did you use?
Folderitem = nil?
Folderitem.exists ?

A folderitem can be valid even if it does not exist, so is .exists true at this point?

How do you make the folderitem?
I recently found that constructing a folderitem using a stored absolutepath gave me a folderitem that wasnt what it should have been.

So at the point when you cannot read the file,
what is the value of the .nativepath property, and
what is the value of the .exists property?

Thanks, Jeff, I’ll try to answer all that. I started work on this app about six weeks ago on my laptop in Australia using the latest Mac PowerBook OS after not using Xojo for a couple of years. (It’s important to know that I had no serious problem with it until about 24 hours ago (after installing Mac OS 10.15.7 on my iMac in England)).

I had to remind myself how Xojo worked so I experimented with folderItem, creating folders and files in my Documents folder. I created a “xojoData” folder programatically and within that two folders, call them “folderA” and “folderB”.

I had two main routines to output and input a text file. My input/output code was pretty much the same:

//Dim everything needed including folderItems d, f, g, h
//In particular Dim d As FolderItem = SpecialFolder.Documents
//and text input or output stream t
If d <> Nil Then
  f=d.Child("xojoData")
  if f<>Nil then
    g=f.child(“folderA”)
    If g<> Nil Then
      h=g.child(“diskFile.text”)
      if h<>Nil and h.exists = true then
        t=TextOutputStream.Create(h)
        //do stuff
      end
    end
  end
end

That’s from memory so I may have a typing error in there.

Then I got a file of words off the internet, dumped the text in a named .txt file in folderA and input it into my app, sorted everything by length into arrays and then spat them out again as lists with names like “list3.txt”, “list4.txt” etc so I could access them by length in future. Those files were Xojo created. I accessed several of those files later using TextEdit, more to look at them than change them. Everything worked fine in the app with input and output.

When I got back to England about two weeks ago, I shifted to using my elderly iMac because the screen is bigger but that didn’t seem to create any problems. I had a fresh download of the latest Xojo on the iMac although my app in progress was on my iCloud.

After a while (several days) when I started using my file input routines, I started getting the alert which I mentioned at the start of this thread, “myapp.debug.app” would like to access files in your Documents folder. Not serious, I just had to click on the OK button, but a bit irritating.

I discovered I could avoid this irritation by dragging a copy of my xojoData folder to my iMac’s “Application Support” folder and using a path to get there so I replaced:

Dim d As FolderItem = SpecialFolder.Documents

with

Dim d as new FolderItem("/Users/imac27/Library/Application Support")

The alert window stopped bothering me and I carried on with developing the code. Then, within the last day or two, I realised I was getting problems with my data not loading. I assumed I had inserted a logical error somewhere in the code I was developing, although I couldn’t see what it was.

Eventually, I tracked the problem down to the textfile input routine. In the debug, it would go right through to the line

if h<>Nil and h.exists = true then

Actually that line had become just

if h.exists = true then

At that point the debug app just skipped to the end, obviously deciding that h did not exist

I changed it to

if h<>Nil then

And the debug got past that line, but when it tried to do a readLine, it failed and skipped to the end.

At that point I tried reverting to using the Documents folder again simply by changing back to

Dim d As FolderItem = SpecialFolder.Documents

I had never moved the folder xojoData that had been working - I had just copied it, dragged the copy to the new location and given it the original name.

But that was no longer working - the debug just skipped to the end after trying to implement the line referring to folderItem h.

Then I looked at the information windows on my text files, saw that the files seemed to be owned by TextEdit and tried changing the “Open With” entry to Xojo but that didn’t help.

I hope that answers all your questions. - Steve

I recently had some similar fun on Monterey. My app couldn’t open a database from a value in the preferences. For some reasons the stupid “do you want to” dialog wasn’t shown. Instead the folderitem was treated as being nil. I had to do code-signing even in debug.

Pretty please: don’t nest your code so much. And you can reuse the folderitems. Something like:

if myDocument <> nil and myDocument.exists then
  myDocument = myDocument.Child("whatever")
end if
if myDocument <> nil and myDocument.exists then
  myDocument = myDocument.Child("other folder")
end if

Its starting to sound more like you are being gaslit by MacOS than the code being at fault.
And that will likely come down to code signing/notarisation

But: try this for creating:


d = specialfolder.applicationdata    
// preferably not  /Users/imac27/Library/Application Support
// but if your app is translocated by MacOS, there could be two sets of Application data
// and documents.. One which you see as a user, and one that only your app sees 
// because MacOS treats it in a similar way to another user logged into the machine
// until it is code signed and trusted



  f=d.Child("xojoData")
  if not f.exists then f.createasfolder
    if not f.exists then msgbox "Problem detected"   //should be ok, though
    g=f.child(“folderA”)
   if not g.exists then g.createasfolder
   if not g.exists then msgbox "Problem detected"   //should be ok, though
     
     h=g.child(“diskFile.text”)    // nb if we had to create folder above, this cannot exist 
      if h.exists then
        t=TextOutputStream.Create(h)    // Note this creates the file, yes??
        //do stuff
      end if
    end if
  end if
end if

Now, if you used that code to create files, the next step is to look in the folder d
(documents or application support)
and ensure that the folders, sub folders , and files have been created.

if they have NOT, then its a permissions issue, which the interim code signing might solve.
An alternative would be to use the system preferences to set ‘full disc access’ for your app and the debug version of it:

once the files exist, reading them back should be code like this


d = specialfolder.applicationdata    
  f=d.Child("xojoData")
    if not f.exists then msgbox "Problem detected"  
    g=f.child(“folderA”)
   if not g.exists then msgbox "Problem detected"  
     
     h=g.child(“diskFile.text”)   
      if h.exists then


        //Open with a text input stream

      end if
    end if
  end if
end if

Full Disk Access only is possible when the app (even when debugged) is codesigned.

1 Like

should have read
if not h.exists
, but I spotted this more than an hour ago, so forum wont let me fix it. Go figure.

I think Ventura is number 13, actual Monterey is 12.4.

So what is this macOS version ?

Emile, it’s Catalina, my iMac won’t go any higher :frowning: but it has a big screen

Jeff, thank you so much for your time. I tried your code and couldn’t even run it because I got error flags from the line g=f.child(“folderA”). I searched the iMac hard drive and found only two xojoData folders, the one in my Documents folder and the one in my Application Support. They both contained exactly duplicate sets of properly named folders and files and clearly SpecialFolder.ApplicationData was finding the Application Support xojoData and this existed as far as Xojo was concerned because it threw up no error flag.

The first thing I tried was to remove everything inside xojoData, create new folders on the Mac and drag everything across. The new folders were still regarded as not existing.

I couldn’t quite believe this at first, but eventually I recreated the whole folder structure again programatically and then dragged everything across. Bingo, everything back to normal. No problem with the files, just the folders, so still, perhaps a problem with OS 10.15.7 rather than with Xojo. The original folders were Mac created, I think and were behaving OK before my OS update.

Thanks again for your valuable help! Steve