One of my users is on Monterey and I’ve tested my app to work properly up to Ventura, but for some reason his computer will not let the app read files from Library/Preferences or Application Support. These are plain text files created natively by the app. Never had this problem before.
I see FileVault is turned on by default in Ventura (i turned mine off). Would this interfere with reading the files if it’s turned on? I’m guessing it’s turned on by default in Monterey as well.
What is the code? What error do you get? Did the user restart his computer?
I have had a few cases of users not having access to their own Application Support folder. A restart usually fixes this. The Preferences file should be a plist and not a plain text file.
I assume you mean ~/Library/Preferences, because Library/Preferences shouldn’t be writable in the first place. This is a system location and typically requires privilege escalation to access from a user space application.
Since Mac OS X 10.9 Apple have been advising against manually reading and writing to the User preferences folder (~/Library/Preferences). You are supposed to use the Apple preferences system that they introduced in Mac OS X 10.0. Check out the 11 year feedback report requesting this functionality https://tracker.xojo.com/xojoinc/xojo/-/issues/18346. If you have a copy of the now discontinued Ohanaware App Kit, it includes code to access NSUserDefaults. If not, I’m sure a MVP can sell you a plugin for it.
The application support folder is also one of the area where Apple have guidelines on how to use. Make sure that the subfolder your application creates is the BundleID of the application “~/Library/Application Support/com.ohanaware.appWrapper4RG2”.
Thanks for all the suggestions. This is what happens when an old art major learns to code. I see how things SHOULD be, but if 2 computers are using the same app on the same OSX version, how could it work on one and not the other? That does not seem logical to me.
You basically need more information as to what might be causing this problem.
If it were me, I’d start by ensuring that you’re accessing the correct paths. They MUST point to the User data and in the case the preferences folder, do not try to use it in the way you are. Either learn how to use declares to access the Apple preferences system or write your prefs file into the Application Support folder (the users one, not the system one).
Next I’d write code to create an error message if it fails, one of the things I’d check is the permissions on the file (if it exists) or permissions on the folder if the file doesn’t exist.
Think about (and ask the community) things that can be different and how to test for them when things fail. The more information you can gather, the higher possibility you can relay a helpful error message that can either help your customer directly solve the issue or provide information to you to help you understand the error.
I’ve been doing it this way since 2007 and never had an issue until now. You would think Apple would have flagged that when I submitted to the MAS, but it’s been available there for years with several updates.
I have error codes but they only tell me that those files could not be opened for some reason. I had the user check the file permissions and they are Read & Write like mine are. Can it be, though, that if he doesn’t have admin privileges it won’t work? If so I can’t believe I haven’t had this issue years ago.
It is entirely up to you guys what you do with your apps, I am merely pointing out that you’re going against Apple’s guidelines. They’re only guidelines, until someone at Apple decides to make 'em rules.
On the plus side, Apple’s NSUserDefaults is really easy to use in your application as it is basically a dictionary, you simply set or read whatever you want and let Apple handle how the data is stored to disk.
The user has tried on several Macs at his business with the same results, so I’m doubting it’s a matter of restarting or logging in again. Wondering if their IT department has something preventing proper permissions. He said they don’t, but it does seem odd. I also tried creating another user on my Ventura machine that had standard permissions (not admin) and it ran fine there too, but it was installed using admin account. Maybe I could delete it and try reinstalling from the test account.
Thanks for all the suggestions. I will try to rewrite how preferences are accessed. I’m not familiar with declares, though. Are there any good tutorials available you can recommend? Sample code?
Can you share a small and simple functional sample of what you are doing exactly, specially exposing the reproducible and offending part? Sometimes people do things exotically and other people can find something and offer a solution.
I think i got the if t <> nil from someone else’s code at the time. I didn’t understand it either.
Here is how I’m reading in the data in the getPrefs method. Each line in the file represents some data point saved in the preferences window of the app then written to the preferences file by a savePrefs method…
You can check by yourself. Using the IsReadable, IsWriteable, Permissions, Owner and Group properties of the folderitem, you can see whether your file or its parent folder has permissions you wouldn’t expect. You could then warn the user with a dialog, telling the exact cause.
There are two issues with that code:
• You don’t check if f=nil. When ApplicationData.child(“MyApp”) doesn’t exist, f will be nil in this code (and “if f.exists then” will raise a NilObjectException).
• If, for whatever reason (mostly permissions issues), ApplicationData.child(“MyApp”) isn’t accessible, your long line assigning to f will raise an exception. It’s usually better to split the line:
f=specialFolder.ApplicationData
if f<>nil and f.Exists then f=f.child(“MyApp”)
if f<>nil and f.Exists then f=f.child(“MyApp”)
(you might remove the “f.exists” intermediate calls, as a non-existent folder would turn f to nil; just always check for f<>nil; and check f.exists for the final file).
In the past, there used to be less exceptions raised, and checking whether the stream was nil was a catch-all solution.