Friday, June 17, 2016

how to create a project template

Leave a Comment

On the subject of custom templates. I am teaching myself how to do this with xcode 7 and objective c and I am stuck. So far, through reading other posts on S.O. I have managed to create a custom template by copying the Single View application one and dropping it in the right directory of xcode packages. My template folder looks like this:

enter image description here

If I click on Main.storyboard and say add a few buttons, and save it, and then open my custom template in xcode, the buttons are there, so I know I am making progress. What I would like to do though, is create view controller files and xib and include app icons etc... so that I can have a properly customized template to start all my projects with. And this is where I am stuck. I am not sure how to do this starting from the simple file Main.storyboard. Could anyone please just point me in the right direciton.

Particularly, what I am looking at doing is not having a storyboard at all and start with an xib. I am guessing I need to do something with the TemplateInfo.plist. I have looked and looked and can't find anything about it, so just a redirection would do. Thanks

1 Answers

Answers 1

Creating Xcode templates can be quite complex because most anything that can be edited a project can be scripted. To reiterate what you already know, one should create a new folder in the ~/Library/Developer/Xcode/Templates directory. This is one of the locations Xcode scans on project creation. Naming this folder "Custom Templates" for example will make it show up under that name in Xcode's project creation dialog. In this new folder create another folder named "baseApp.xctemplate". This will make a template named baseApp appear once all our files are in it.

Starting new templates is easiest done by copying one of Xcode's existing ones. Mostly because writing the all-important TemplateInfo.plist from scratch can be cumbersome. These files are located in the Xcode app. Show its contents in the finder and navigate to: /Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Templates/Project Templates/iOS/Application

From the "Single View Application" template copy all 3 files to the baseApp.xctemplate folder made earlier. This next step is crucial, but after that the first template is all but ready. Double-click the TemplateInfo.plist file to open it in Xcode and change the last part of the Identifier key to baseApp. That's it - the new project dialog in Xcode now should look something like the image below. It would be a good idea to change your TemplateIcon.tiff. Other than that BaseApp is complete with options for Objective-c as well as Swift, Storyboards, CoreData support and more.

enter image description here

Now create a new Xcode project named "xibApp" based on the new baseApp template (no options). Then follow these 4 steps:

• delete Main.storyboard & ViewController (move to trash)

• delete the "Main storyboard file base name" entry in the Info.plist

• add a new Cocoa Touch Class called ViewController based on UIViewController and check the box to include a xib file

• replace the didFinishLaunchingWithOptions function in AppDelegate with:

    window = UIWindow.init(frame: UIScreen.mainScreen().bounds)     window?.backgroundColor = UIColor.whiteColor()      let viewController = ViewController()      window!.rootViewController = viewController     window!.makeKeyAndVisible()      return true 

You should now be able to run the app. If everything looks OK quit Xcode. Duplicate the baseApp.xctemplate in your Custom Templates directory and rename it to "xibApp.xctemplate". Then delete the Main.storyboard file in that directory and copy AppDelegate, Info.plist, ViewController.swift and ViewController.xib files from the xibApp folder to the xibApp.xctemplate folder. Double-click the TemplateInfo.plist in the xibApp folder to open it in Xcode and rename the identifier to "com.apple.dt.unit.xibApp". Another thing that needs addressing is the first of the ancestors in this file. It is set to "com.apple.dt.unit.storyboardApplication" and if left would make all resulting projects into storyboard projects. In order to remedy that we are going to create our own ancestor.

Xcode uses the ancestor hierarchy to include whole trees of projects. Any folder with the extension .xctemplate can serve as ancestor as long as it is in an Xcode directory - either the app's itself or in ~/Library/Developer/Xcode/. Additionally these directories have to contain a TemplateInfo.plist file that is set up correctly. So grab the TemplateInfo.plist inside "Cocoa Touch Application Base.xctemplate" which is located in the contents of the Xcode app (Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Templates/Project Templates/iOS/Application). Put this file in a new folder inside the "Custom Templates" folder and name the folder "Custom Xib Base.xctemplate". The name of this folder will become the name for our ancestor. Xcode will delete all spaces in the name and make it into "customXibBase" and that's our new ancestor's extension: "com.apple.dt.unit.customXibBase". Since the Custom Xib Base.xctemplate folder may become an ancestor to other templates, it may be a good idea to move it to a new aptly named sub-folder in the Custom Templates directory (i.e. "shared").

enter image description here

Back to the TemplateInfo.plist inside the xibApp.xctemplate directory. Double-click it, click the disclosure triangle next to Ancestors and under item one replace "storyboardApplication" with "customXibBase" so that the whole line reads "com.apple.dt.unit.customXibBase". Finally we need to provide Definitions and Nodes for the 4 files we are including as seen in the image below (AppDelegate, Info.plist, ViewController.swift and ViewController.xib). Save the file and quit Xcode. All done. enter image description here If everything went alright there should now be a new project template under the Custom Templates category called xibApp! I would consider this a workable but hackish approach towards generating new templates. It will probably break with newer versions of Xcode. But it's a good starter to further explore project templates.

The final TemplateInfo.plist for xibApp.xctemplate:

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict>     <key>Kind</key>     <string>Xcode.Xcode3.ProjectTemplateUnitKind</string>     <key>Identifier</key>     <string>com.apple.dt.unit.xibApp</string>     <key>Ancestors</key>     <array>         <string>com.apple.dt.unit.customXibBase</string>         <string>com.apple.dt.unit.coreDataCocoaTouchApplication</string>     </array>     <key>Concrete</key>     <true/>     <key>Description</key>     <string>This template provides a starting point for an application that uses a single view. It provides a view controller to manage the view, and a storyboard or nib file that contains the view.</string>     <key>SortOrder</key>     <integer>1</integer>     <key>Options</key>     <array>         <dict>             <key>Identifier</key>             <string>languageChoice</string>             <key>Units</key>             <dict>                 <key>Objective-C</key>                 <dict>                     <key>Nodes</key>                     <array>                         <string>ViewController.h:comments</string>                         <string>ViewController.h:imports:importCocoa</string>                         <string>ViewController.h:interface(___FILEBASENAME___ : UIViewController)</string>                         <string>ViewController.m:comments</string>                         <string>ViewController.m:imports:importHeader:ViewController.h</string>                         <string>ViewController.m:extension</string>                         <string>ViewController.m:implementation:methods:viewDidLoad(- (void\)viewDidLoad)</string>                         <string>ViewController.m:implementation:methods:viewDidLoad:super</string>                         <string>ViewController.m:implementation:methods:didReceiveMemoryWarning(- (void\)didReceiveMemoryWarning)</string>                         <string>ViewController.m:implementation:methods:didReceiveMemoryWarning:super</string>                     </array>                 </dict>                 <key>Swift</key>                 <dict>                     <key>Nodes</key>                     <array>                         <string>ViewController.swift:comments</string>                         <string>ViewController.swift:imports:importCocoa</string>                         <string>ViewController.swift:implementation(___FILEBASENAME___: UIViewController)</string>                         <string>ViewController.swift:implementation:methods:viewDidLoad(override func viewDidLoad(\))</string>                         <string>ViewController.swift:implementation:methods:viewDidLoad:super</string>                         <string>ViewController.swift:implementation:methods:didReceiveMemoryWarning(override func didReceiveMemoryWarning(\))</string>                         <string>ViewController.swift:implementation:methods:didReceiveMemoryWarning:super</string>                     </array>                 </dict>             </dict>         </dict>     </array>     <key>Definitions</key>     <dict>         <key>AppDelegate.swift</key>         <dict>             <key>Path</key>             <string>AppDelegate.swift</string>             <key>TargetIndices</key>             <array>                 <integer>0</integer>             </array>         </dict>         <key>Info.plist</key>         <dict>             <key>Path</key>             <string>Info.plist</string>             <key>TargetIndices</key>             <array>                 <integer>0</integer>             </array>         </dict>         <key>ViewController.swift</key>         <dict>             <key>Path</key>             <string>ViewController.swift</string>             <key>TargetIndices</key>             <array>                 <integer>0</integer>             </array>         </dict>         <key>ViewController.xib</key>         <dict>             <key>Path</key>             <string>ViewController.xib</string>             <key>TargetIndices</key>             <array>                 <integer>0</integer>             </array>         </dict>     </dict>     <key>Nodes</key>     <array>         <string>AppDelegate.swift</string>         <string>Info.plist</string>         <string>ViewController.swift</string>         <string>ViewController.xib</string>     </array> </dict> </plist> 

Any issues with this answer? Please let me know :]

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment