Hello all. Our team recently pushed a JUCE app to the Mac App Store, and since there doesn’t seem to be anyone else who has talked much about this, I wanted to briefly summarize what all was involved in getting a JUCE app past review and provide a little reassurance that yes it can be done!
For reference and to show that it really is possible to have a JUCE app on the App Store, our app is here.
The main App Store manifesto is here. Though it is a long list, most items are easy to comply with; however, there are a few items that require careful consideration.
2.1 Apps that crash will be rejected
2.2 Apps that exhibit bugs will be rejected
2.3 Apps that do not perform as advertised by the developer will be rejected
These seem like no-brainers, but I’ll admit we sent a version of our app for review in which clicking a certain button crashed the app, and yes Apple found it and it was rejected. (They provided a crash report in this case.) Test every widget and every feature. Prune developer mode menu items and widgets out of the app. Also, you should know that Apple will test according to your description, so test everything in your description, and be conservative in what you write in that description.
2.6 Apps that are “beta”, “demo”, “trial”, or “test” versions will be rejected
Apple wants finished apps, so even if you know your app is a little rough around the edges, you should probably use a version number of 1.0 or higher and not make any mention of limitations.
2.31 Apps that are not sandboxed appropriately may be rejected
You now have to sandbox apps. See below for additional information on sandboxing.
6.1 Apps must comply with all terms and conditions explained in the Apple Macintosh Human Interface Guidelines (HIG)
This requirement is tricky since JUCE inherently uses non-native controls. The most important thing, however, is to use the Mac main menu and use native title bars. Beyond that, you have two options: you can use a NSViewComponent and use native controls (fairly difficult) or you can turn your app’s look and feel into a full-blown skin. Apple doesn’t seem to mind custom skins (as pointed out in this thread), but they are especially sensitive to anyone who imitates native controls. As much as you might want to try to make things look like Cocoa, unless you are going to be pixel perfect (and remember it’s not just look, but feel that counts), don’t bother. You are better off subclassing a LookAndFeel and making a slick skin with style. The Mixxx and VirtualDJ Home apps on the App Store are other precedents for music apps that got away with using custom skins.
Your App icon must contain Retina “@2x” images, which means your icon size must now derive from a 1024x1024 dimension image. The easiest way to make this file is to use the iconutil command which is documented in the HIG.
You should use a bundle identifer in your Application Support folder location. See non-sandboxed (10.6) and sandboxed (10.7/8) locations. It seems almost everyone puts data in ~/Library/Application Support/AppName but according to those articles it should be ~/Library/Application Support/bundle.identifer or ~/Library/Containers/bundle.identifier/Data/Library/Application Support/AppName if sandboxed. Note: JUCE correctly determines the location of the Library folder when sandboxed using userApplicationDataDirectory (~/Library when running 10.6 and ~/Library/Containers/bundle.identifier/Data/Library when sandboxed on 10.7/8). To make things simple, we use the bundle identifier for the Application Support folder whether running sandboxed or not.
Apps are now required to be sandboxed. Sandboxing is the Apple equivalent of a chroot jail. Your app’s data is wrapped in a container. By default your app has no access to user files, the network, the microphone, and so on. To enable these things, you create entitlements which privilege your app for specific features, but be warned, you will have to declare all your entitlements to Apple and explain in sentences why you are using them in the iTunes Connect application metadata fields.
In our case, we use the microphone for recording and the network for downloading files off the web. These were easily enabled using the microphone and (incoming) network client entitlements. No extra work was needed after enabling the entitlements.
To get access to user files, you will have to use the native open/save panels (accessible using the FileChooser) and have the user-selected file entitlement enabled. (There are other entitlements if you want access to specific user folders like documents, music, etc.) Note that this user-selected business can make your life a living hell because it is not sticky across sessions. As was noted, it will break any kind of Open Recent list you keep in your app. My suggestion would be to just forget about it and focus your efforts on more important things. If you are used to being a perfectionist, get used to being a pragmatist It also means that when saving you only have access to the one single file that the user entered in the save panel. You won’t be able to change the filename after you get the file selection—you will not have access to any other files. It seems that the OS remembers the files the user selected for a single app session. There is nothing else you have to do, but just know that if you don’t have access to a file, you will fail both reading and writing. A bug was recently fixed regarding file extensions in the open/save panels.
Overall App Store Process
The App Store requires you to code sign and upload the app using Xcode. While beyond the scope of this post, the basic process is:
[list=1]Register/pay for the Developer program. Download the latest OS X with redemption code.
Create an App ID/bundle identifier, get your developer/distribution certificates, register your computer ID, and create a provisioning profile.
Make sure your bundle identifier is in your plist as this gets compared to the provisioning profile.
Set your Xcode project to code sign using the provisioning profile created in the Developer portal. Set the target to 10.6 if possible.
Turn on Sandboxing and set your entitlements.
Make sure you have a Retina-compatible icon and are building with your Debug Information Format set to DWARF with dSYM.
Test out building your app by doing Run (which builds the Debug configuration).
Archive the app (builds the Release version suitable for App Store).
In iTunes Connect, register your app, provide all the metadata, write a modest/conservative description, and declare any sandbox entitlements you are using. Note that the version must match the one in your .plist.
In the Xcode Organizer, validate the archived app you created. This does a simple check of the build to make sure it is sane and fits their requirements.
In Organizer, distribute the archive app and export the application to disk and test, test, test.
When you are sure you want to proceed, submit the archive for review in Organizer.
Bide your time for about this many days. Note that while your app spends most of its time “Waiting for Review”, the “In Review” stage in my experience can take anywhere from 15 minutes to two days.
Apple will let you know the result of their review. If they misunderstood something, you can write back to them and they will then look at it and reconsider generally within a day. Otherwise, your binary is rejected and you need to go back and twiddle and stand in line again.[/list]
Hope this helps! Cheers!