I submitted my first iPhone app to Apple for review on Thursday. The process didn’t go smoothly; there were issues I probably should have known about, and issues that seemed to have been compounded by using my client’s keys to release under their developer account. Now that it’s in Apple’s hands, I feel I should write down the issues and resolutions I encountered, even at the risk of looking like a doofus at times. To be trite, if it helps just one future developer have a smoother release it will be worth it—odds are, that future developer will be me.
Warning: If you are not an iPhone developer and don’t plan to be, you should consider skipping this post. It’s minutia you will never use, and I don’t offer a refund for your time or brain cells spent reading this.
Profile Fun
The session started off with the client stating that he couldn’t get the code running with his Developer and Ad Hoc profile on his phone (I had been giving him milestone releases signed with my Ad Hoc profile which (mostly) worked just fine). I’m still not convinced that the combination of both Developer and Ad Hoc is desirable, let alone valid, but that’s beside the point—in the absence of being able to convince myself it was invalid such that I could convince him it was, I would do my best to make it happen.
I got it working with the Developer profile pretty easily, but Ad Hoc was elusive. I installed clean copies of the mobileprovision files a few times, with and without restarting Xcode to “be sure,” but still no joy.
Where are my profiles?
It’s best to trust the Xcode Organizer to manage the provisions, but there are times when you feel the need to directly manipulate. Installed mobileprovision files are found in ~/Library/MobileDevice/Provisioning Profiles/
but if you don’t remember that, Spotlight doesn’t help because it doesn’t return results from the ~/Library/
hierarchy without some contortions. You can use mdfind "kMDItemContentType=com.apple.iphone.mobileprovision"
to find all the profiles on your machine. The documentation in the iPhone Development Guide is currently out of date, claiming the directory to be ~/Library/MobileDevice/Provisions
(the error reporting page threw errors when I tried to file a bug on it—I’ll try again later).
The real problem? The profile was for App Store Distribution, not Ad Hoc. Both kinds of profile say “iPhone Distribution” in Xcode, so no information gained there. I found it suspicious that his profile didn’t list any devices, but didn’t feel I could assume that just because he hadn’t added a device to the provision implied that it was for the App Store. As it turns out, that assumption is correct: App Store profiles can’t have devices specified, and the Program Portal won’t let you create an Ad Hoc profile without at least one device specified.
Is my mobileprovision file for Ad Hoc or App Store?
Do one of the following:
Within the Program Portal, go to Provisioning > Distribution and find the profile in question. Click Edit on the far right of that row, then choose Modify from the menu that appears. You will be shown the page you used to initially set up the profile, including the Distribution Method.
Grep the mobileprovision file for “ProvisionedDevices”. The presence of that key indicates an Ad Hoc profile, otherwise it’s for App Store.
At this point, some of you may be rolling your eyes at my client—please stop. I don’t know anyone who has felt that this process and the Dev-vs-AdHoc-vs-AppStore distinction were clear when they first encountered it. Working with profiles isn’t an everyday thing; once you get it working you tend to just use it the way it is and as a result that knowledge doesn’t necessarily stay in long-term memory. Creating your own profiles also allows you to name the profile descriptively, whereas trying to determine whether someone else did it “right” is not immediately obvious. This was an interesting challenge for me, but I don’t fault him at all.
Submitting the App to iTunes Connect
So, we’ve determined that we’re working with an App Store profile not Ad Hoc, and at this point have decided to skip attempting the Ad Hoc and move on to submitting for review. The first task is to find iTunes Connect; the Program Portal User Guide says you “will find a link to iTunes Connect in the ‘Distribution’ section of the Program Portal”…but it’s a bit more hidden than that.
Getting to iTunes Connect
Do one of the following:
In the Program Portal, go to Distribution > App Store. Click “Learn More” in the “App Store” section of the text to reveal more steps to follow. Step 2 has a “Go to iTunes Connect” link.
Or just go straight to http://itunesconnect.apple.com/ (which is definitely a “duh!” moment once you know).
Fill out the overview form. Liberally click the circled question marks for descriptive help.
Upload Gotchas I Encountered
The application’s zip archive to upload cannot have a space in the name. From now on, I plan to rename all my application zips to CamelCased alphanumeric only.
The screenshots need to be .jpg or .tif even though the screenshots obtained in Organizer are .png. I realize I’m not the first person to observe this, but I serve as evidence that it bears repeating.
When I uploaded the application zip, I would be told that the application was invalid, so I clicked the “Check here to upload your binary later” checkbox to allow me to upload all the (corrected) images and continue setting information about the application. Most of that was self-explanatory, or at least answerable by my client (“How much do you want to charge?”). That checkbox is pretty magical—you can fill out everything about your app but the app itself and leave that to the last step. I plan on making that my modus operandi for every future app.
Fix the App Signing
There were still two more layers of the app submission onion I needed to peel away. The first was to figure out why my app archive was “invalid.” Once again, I did numerous clean-and-build cycles to check that the Build Output window looked like it was signing correctly and generating the files as expected. I downloaded “fresh” copies of the mobileprovision files and reinstalled them in Xcode in case all the twiddling I’d done earlier had corrupted something.
Then I finally slapped my forehead when I realized that the signing had continued to use “iPhone Developer” not “iPhone Distribution”. In the mass of build output text, I’d mentally reduced to “iPhone D” and called it a match. I went to the target’s build settings in Xcode, changed the Code Signing Entity to the “iPhone Distribution” entry, cleaned all targets, rebuilt and…it was still signing with “Developer”. No matter how many times I toggled the build setting, it refused to use a different profile.
Searching the web, I mostly found suggestions to delete lines in the pbxproj file where PROVISIONING_PROFILE and CODE_SIGN_IDENTITY were defined. After making a backup of the file, I went for the nuclear option and stripped the lines. I started Xcode back up and reconfigured the now-empty Code Signing Entity setting, cleaned targets, rebuilt and…it signed with “Distribution” finally!
As I said, I consider this a nuclear option. Future releases and projects will probably follow Craig Hockenberry’s advice for sharing projects once I get my brain wrapped around it better. Until then, “grep -v PROVISIONING_PROFILE MyApp.pbxproj | grev -v CODE_SIGN_IDENTITY > MyAppStripped.pbxproj
” will help me out.
Zip the application, camelCase the zip file, upload to iTunes Connect…and the app is valid! But one more hurdle: I am told that the bundle identifier contains disallowed characters. This is relatively easy to troubleshoot: The project template of “com.yourcompany.${PRODUCT_NAME:identifier}
” translates spaces in multi-word product names to an underscore (“My App” becomes “My_App”) which is not allowed. Simple troubleshoot, simple fix: As much as I would like to figure a correct way of using the variable substitution (this app changed names a few times during development), at this point I’m willing to just hardcode that last piece of the identifier to a camelCased version of the product name.
Cleaned targets, rebuilt, zipped the application, camelCased the zip file, uploaded to iTunes Connect…
SUCCESS!
So there the app sits, with a little yellow “In Review” globe in the status field. I plan to do a post discussing what I learned during the development of the app, but will wait until it’s actually approved by Apple since numerous changes and learning opportunities may still be in store.