Mac App Store Submission - File Locations & Sandboxing

Thats the right place for user-created documents to be shared.
The stuff that goes into Application Support is not usually customer-facing.
And it is usually to be deleted along with your app (if removed), where a document you create would not be.

You can save into the app support folder without a ‘save as’ dialog, obviously.

Hi Jeff. Ok, so if the “Documents” folder is where user documents are supposed to be shared, how can I create a folder structure such as “Documents>My App Name>Projects” and “Documents>My App Name>Templates” on first launch without user interaction? I’m assuming I can’t, unless on first launch before any window opens I ask the user via a message dialog to select a folder and give me permission to access the “Documents” folder (for example) and then store a Security Scoped Bookmark to that folder and then create the folder hierarchy? Correct?

In the app I put into the App Store, it does exactly that.
Folder in documents, sub folder with stuff.

I confess I have no idea about ’ Security Scoped Bookmarks’
Didnt use one…

So on launch you ask the user to select a folder?

When did you submit your app to the app store? If you sandbox your app you would need to store a reference to the security scope otherwise on the next launch the user would not be able to open files within the Documents folder.

It appears that a sandboxed app lives in a ‘container’ which has it’s very own Documents and Application Support folders.
So as not to tread on the toes of other apps.

So where are you supposed to save documents? In the container docs folder or the user docs folder? And I haven’t tried yet but I assume the same issue will arise trying to invoke SaveAsDialog and setting initial directory to Documents within the container?

And how do you access the container documents folder without hardcoding a long path? It seems SpecialFolder.Documents in a sandboxed app behaves exactly the same as a non-sandboxed app and reverts to the user’s main Documents folder.

Jeff, if you have recently submitted your sandboxed app to the app store and it was accepted and you say you save user documents to the container’s documents folder without using security scope bookmarks and everything works fine and you and your users can easily access everything after app close and re-launch then perhaps you can share the code you are using to save and open to these sandboxed folder locations?

My guess however is that something is being lost in translation here and the information you are giving me may not be entirely correct or at least missing some crucial parts to it. I appreciate your answers, I truly do, but none of what you are saying is making much sense in practical terms during my testing.

Thanks again and I hope you can clarify.

This is your main problem. YOU don’t. The user does. Present them a SaveDialog, and forget it. You really are fighting the paradigm here.

Please stop setting InitialDirectory. Mac handles this automagically for you. The dialog will open with the last directory the user navigated to in your app. This is the expected operation, as it’s a system level one.

Again, you don’t. Present an OpenDialog for the document, and the user will select the document, giving you access to it in code.

I agree with Tim.
I have no idea what a security scope bookmark is.
My open/save code looks exactly the same in my MAS app as it does in my non-MAS app.
I don’t care where the user saves their files.
And I happily use SpecialFolder.Documents throughout.

Sorry.

[quote=355751:@Jeff Tullin]I confess I have no idea about ’ Security Scoped Bookmarks’
Didnt use one…[/quote]

I wrote an article in issue 13.2 of the xDevmag.com which talks about understanding the Sandbox and what to use and when.

But I’ll just simplify here; In the lifecycle of the application (from when it opens) the user is able to open and save documents without (almost without) hinderance, providing you use the Xojo OpenDialog and SaveAsDialog, and have the correct entitlements. Once a document is opened or saved by that application the app can access it freely at any time, until the application is quit (or crashes).

When the app is restarted it loses security clearance to access the files the user was last using, basically it cannot automatically re-open the last documents. If you don’t need this, then great. If you do, there’s a bunch of things you can implement. The easiest being the Apple Recent Items menu (via the SandboxKit), the more complex would be Window Restoration (again via the SandboxKit).

The last and I mean really the last option, that should only be considered if all else fails is Security-Scoped Bodegmarks. I’ve well documented their fundamental flaws through this forum, you should really be aware their shortcomings before you start using them. The biggest thing to be aware of is when they fail, for whatever reason, you have no idea of the filename, where the file was and the reason it failed. If you don’t handle them correctly, they will corrupt your application container, which means that your application can no longer access any files, regardless.

Hi Sam. Thanks for your two cents. Although you, Tim and Jeff seem to think I am fighting the Apple paradigm, perhaps sometimes you have to if your application does not fit the “regular” application construct and, as in my case, needs a default folder structure of easily accessible and modifiable pre-existing files (projects, templates etc) outside of the container. I’d happily put them in the container but Apple then doesn’t allow the user access to them via Open and Save dialogs. So that’s poor design on their part.

Two questions:

  1. Security-scoped bookmarks in my opinion is the solution I am going with because I have managed to get it to work quite well by storing a reference to them and always pairing off the request and release calls. You mention there are issues when they fail and I’ve read a few posts where you have commented but can’t find anything specific about this except for you mentioning issues if the scoped folder moves and with alias issues etc. Can you please point me to your post(s) about how a “bodgemark” could fail and corrupt a container?

  2. It seems the only way for me to get my app to work the way I require is to initially prompt the user via a modal dialog to select a folder on the app’s first launch and then store a bookmark to it and then open the main app. This would obviously only happen once. Do you think this is okay in terms of MAS inclusion or do you think the reviewer might not think this is Apple’s way and reject it?

Hi,
for a sandboxed app I’d follow your point 2): i.e. when the app launches the first time

  • I’d show a message dialog telling the user to select a location (Hello cocoa.username, the app needs…; So in the dialog that will show up select a location and click “New Folder”; If you do not proceed now, you will be prompted again.).
  • the message dialog contains a “Proceed” and a “Cancel” button, in order for MAS not to reject the app because of forcing users etc. etc.
  • if the user clicks “Proceed”, show a SelectFolderDialog where the user, prompted by the previous message, selects a location and clicks the “New Folder” button. And you store your bookmark.
    -if the user clicks “Cancel”, when he/she attempts to create/open one of the templates, follow the same routine.

So you can keep templates in the specialfolder, and maybe copy them to the bookmarked location when the user opens one of them. But here I’m just guessing as I do not know your exact open-procedure. In my particular case I show a listbox showing available files; user selects a row and clicks one of three buttons: “move to bookmarked.location.name”, “move and open”, “cancel”; where “move” means copyfile. This in order to please MAS reviewers and not to have them complain about forcing users. Circuitous route indeed, but I do not care so much since in my app this need is seldom felt. In your case I would risk a direct approach and see if MAS lets it go.

BTW cocoa.username refers to the cocoa function that returns the user name; users get more comfortable and do not panic when addressed by name.

And yes, I follow something like this routine and MAS has never objected.

Hi Carlo. Thank you for your advice. My only issue is that I would need to have a select folder button and a quit button because I really would have to get that folder selection nailed-down before launching the app so I can fill list boxes with templates etc.

Do you think having the quit button rather than cancel is a bad idea?

The idea is pretty drastic indeed. At least I’d call the quit button something like Cancel & Quit.
But my approach would be to put a “Create main folder” menu that restarts the routine. In the message I’d tell that if user feels uncomfortable proceeding, he/she may click Cancel and select the Create menu to proceed again. In this way user is the one responsible to quit.
Once the bookmark has been created, close or keep disabled the aforesaid menu.

Yes good advice. However, although it may sound drastic, I may just have to try to submit it the way I need it and if it is rejected then try it the other way because not having the main folder established from the get-go will cause all kinds of headaches for me in the programming logic and for the user in dealing with files and templates.

Another question: I have a user manual in pdf and link to it from the help menu. I feel like the user should be able to access this outside of the app and so would like to include it in the user-defined app documents folder. Do you think this is okay?

OK. But when you fill the metadata in itunes connect, apart from selecting the relevant bookmark item, emphasize your need for your procedure. And in the field prompting you to explain to the reviewer the basics of your app, guide him/her step by step, showing again how necessary is your approach. And then hope…

As for the user manual, if I understand correctly, since users will access it from the help menu, I would keep it in specialfolder.applicationdata. But once you have got your bookmarked folder, you can anytime “copy” it there for the user to consult it even after quitting the app. But when making use of the help menu, I’d continue accessing the one in applicationdata. And I’m not sure if your approach in this matter is something a mac-user would expect/appreciate.

Anyway, welcome to the sandbox club, where we have to spend more time thinking how to please MAS reviewers than users.

Lol. Thanks for your advice.