I recently posted about building file templates to create custom playgrounds. Today, I found myself facing a similar dilemma with application extensions. Working with project templates is a bit fussier than file templates, mostly because of the way you customize and register items.
To start, copy a base template from the built-in templates folder. If working with normal Xcode, this is usually /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Templates. With Xcode 6, substitute the Xcode6-Beta file name into the path.
If needed, build a path down from ~/Library/Developer/Xcode/Templates/Project Templates/Application Extension and place the copied template there.
I wanted to build an action extension that wasn’t based on storyboards. You’ll notice that there are quite a lot of files in the modern Xcode 6 template. Since I was only interested in Objective C at this time, I ignored everything that wasn’t part of the ActionViewController.[hm] material. I also deleted the MainInterface.storyboard file from the copied extension.
Next, I had to edit the TemplateInfo.plist file so it would create the right kind of Info.plist for me — that is, one that had a primary class to create (NSExtensionPrincipalClass) and won’t try to load a storyboard (NSExtensionMainStoryboard). The problem is that the property list is actually a meta-property list, one that tells Xcode how to create the actual Info.plist from its template. I recommend highly that you copy the default version someplace before you start editing, so it’s easier to recover from mistakes and try again.
For me, the Info.plist section I ended up with after editing looked like this. And yes, this included all the ampersand-escape sequences. (Escaping the escape sequences for this blog post was a lot of fun. not.) That’s because the template file entry for “Info.plist:NSExtension” includes escaped content in its string values. So be aware that you’re diving into areas that Apple either never intended to become public or did a really poor job of making publicly editable.
<dict> <key>NSExtensionPrincipalClass</key> <string>ActionNavigationController</string> <key>NSExtensionPointIdentifier</key> <string>com.apple.ui-services</string> <key>NSExtensionAttributes</key> <dict> <key>NSExtensionActivationRule</key> <string>TRUEPREDICATE</string> <key>NSExtensionPointName</key> <string>com.apple.ui-services</string> <key>NSExtensionPointVersion</key> <string>1.0</string> </dict> </dict>
Make sure you include any tweaks needed to make your template sound here, including adding and removing file references needed to build the project. Once you’ve done that, go ahead and create or modify the files you want generated in the template’s folder. For me, I edited ActionViewController.[hm] to produce a skeletal no-storyboard version, centered around a navigation controller so that I didn’t have to resort to a standalone navigation bar with a done button. (If you don’t know what I’m talking about, build a new action extension in some project and see how the built-in skeleton is built. It’s not pretty.)
Finally, you’ll need to update the project template’s identifier (Identifier key at the top of the TemplateInfo.plist file) so it doesn’t conflict with the standard template and add a custom description (Description key) to distinguish its use-case. Quit and restart Xcode, and your new template should be visible and ready to use.