How to create project templates in Xcode 4 - iphone

Its really hard to find a tutorial to do this as most information relates to Xcode 3. Answer below may help some people.
I sourced most of my information for the answer below from the following sites:
http://meandmark.com/blog/2011/12/creating-custom-xcode-4-project-templates/
http://www.bobmccune.com/2012/03/04/creating-custom-xcode-4-file-templates/

I spent hours searching the web to find information about doing this. Its not actually that hard to set up project templates for Xcode4.5 but its hard to find information on the web that puts it all together! Hopefully the steps below will help you to create your own.
Setting Up
Lets start by getting a copy of an existing Xcode project template to use as a base. Open finder, go to Applications and right click on Xcode to show package contents. Navigate to Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Templates/Project Templates/Application/
[EDIT]
In Xcode 5 the PATH is as follows: ~/Library/Developer/Xcode/Templates/Application/Project Templates. If Templates/Application/Project Templates not exists you should create it too. Credit to seufagner in the comments below for the update although I have not tried this myself.
[/EDIT]
Copy (do not cut/paste!) one of the listed templates.
Open another finder window and navigate to the following directory (to unhide your Library folder type this cmd in terminal: chflags nohidden ~/Library/ or select press the alt/option key when clicking on Finder/Go) /Library/Developer/Xcode/Templates (you may need to create this folder if not already present) /Project Templates/
Create a folder in here. Call it whatever you wish, a suggestion is your company name. This name appears in the left hand menu of the new project dialogue in Xcode. e.g. in the attached image I've called mine Appscore, there's another one there for cocoas2d.
Paste the project template in here and change its folder name to whatever you wish e.g. MySuperProjectTemplate.xctemplate. We are not done yet though as we need to change the template's identifier. Otherwise it will not appear in the Xcode new project dialogue window.
Open the TemplateInfo.plist file in TextEdit. Search for the Identifier key. You should see a string value something similar to "com.apple.dt.unit.XXXXXX". Replace this with whatever you wish as long as its unique. I again suggest adding your company name and a name that describes the template.
If you now open Xcode you should see the project template appearing under your company name in the new project dialogue.
Customising
At the moment you have a copy of an existing project template which is not very useful. I'm guessing you have a number of classes that get reused in nearly all your projects? How about we include them into this template?
Copy the files you wish, and paste them into your new project template i.e. navigate to /Library/Developer/Xcode/Templates/Project Templates//MySuperProjectTemplate.xctemplate/
Open the TemplateInfo.plist file in TextEdit again. First thing we have to do is tell the project template to include the new files so search for a key called "Nodes" that has an array of values. Add the two following lines:
<string>_VARIABLE_classPrefix:identifier_.h</string>
<string>_VARIABLE_classPrefix:identifier_.m</string>
For example if your controller was called BaseViewController the lines would look like:
<string>___VARIABLE_classPrefix:identifier___BaseViewController.h</string> <string>___VARIABLE_classPrefix:identifier___BaseViewController.m</string>
Next find the Definitions key and you should see a dictionary as its value. In here we have to add a reference to the included files. Create a new key and call it ___VARIABLE_classPrefix:identifier___BaseViewController.h (again taking the BaseViewController as an example).
The value of this key is again a dictionary. It contains a key called Path and a string value which is the name of the file e.g. BaseViewController.h
I've attached the following images to show what I mean as I think my description is falling short. You may notice that there is a key in there called "Group", this as you can guess allows you to create groups and input files directly :D
Hope this is actually useful to someone :) Any questions comment below and I'l do my best to answer. I did this a few weeks ago so my memory is a little hazy.

You can also learn a lot from inspecting the existing project templates, which you can find in:
/Xcode.app/Contents/Developer/Library/Xcode/Templates/Project Templates/
for Mac and
/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Templates/Project Templates/
for iOS.
There are few sample templates also on GitHub by Reid Main and another one by Acani. There are also AFNetworking templates, created by Mattt Thompson. See all the examples, including ones built by Apple and then you can start creating your own.

A good overview of all of the variables used in the plist file can be found here: https://gist.github.com/shazron/943736

#bennythemink
Your answer is really very much help full but I want to add some more things in your answer.
When we copy xcode predefine template than this key contains
<key>Ancestors</key>
<array>
<string>com.apple.dt.unit.storyboardApplication</string>
</array>
this value. When we use this key value in Custom template of xcode it will create AppDelegate class by default. Which we can not move to folder only we can shift it into group.
So i suggest to add this:
<key>Ancestors</key>
<array>
<string>com.apple.dt.unit.objectiveCApplication</string>
<string>com.apple.dt.unit.iPhoneBase</string>
<string>com.apple.dt.unit.prefixable</string>
</array>
value in Custom template so that we will have fully empty template in which we can do any custom stuff.

Related

Rename README.md to custom name and use as a project description

I do apologize if similar question already put, but I haven't found one.
I would like to change the default project description file name (called README.md) to be a custom name (let's say XXX.md) and I wonder if it is possible to be the XXX.md the initial readme file for the project (typical situation: you open the project Code page and you will see the content of XXX.md down at bottom).
I would like to verify if this approach possible in general, but I am mainly interested in Github and Bitbucket services. I briefly checked project settings and I cannot find there such customization. Is it even possible?
GitHub, at least, doesn't provide the ability to do this. It is possible to use a different format (e.g., README.asciidoc or README.rst), but the root file must be called README.
Note that you can include other text markup documents like this and they'll be rendered if they're visited, it's just that they won't appear at the bottom of the file listing like a README will.

How do you create files in arbitrary locations using Swift?

How do you go about creating files at arbitrary locations given you have the absolute path? I want to create a file in some arbitrary location /Users/me/random/project3/<moreStuffInThePath. How would I go about doing this?
To create a directory I would do:
try FileManager.default.createDirectory(atPath: "/Users/me/random/project3/<directoryName>"
This worked fine for directories.
However the counterpart for creating files does not work:
FileManager.default.createFile(atPath: "Users/me/random/project3/something.txt", contents: someString.data(using: .utf8)) // always returns false
I have checked out other stack overflow threads on creating files. Everything I found was about creating files in the .documentDirectory or it was outdated.
Eg: How to create text file for writing
Create empty file swift
Read and write a String from text file
TLDR: How do I create text files/files with random extensions at arbitrary locations on the pc given I have the absolute path?
I would also be grateful if someone could explain why all tutorials available on this matter are about the document directory. Why is it so significant?
Thank you!
This is most likely because your app is sandboxed.
Go to your project settings, select the macOS target and go to "Signing and Capabilities". You should see something like this:
If your app needs to create files in arbitrary locations, you must remove the app sandbox by clicking on the "x" on the top right. Note that this will cause your app to be rejected from the Mac App Store.
If you want to upload your app to the Mac App Store, then you must keep the sandbox, and write to "user selected locations" only. Select "Read/Write" rather than "Read Only" next to "User Selected File". (Although it says "File", this includes directories too) This allows you to write to locations chosen by a user using something like an NSSavePanel.

What steps do I need to take to insert a indexmenu?

I am updating out dokuwiki and redid it from zero because in out old version are errors that i cant fix. Now I downloaded the indexmenu plugin and put it in the right folder. How and which documents do I need to modify to add the treestructure to a not yet existing sidebar?
You need to have a page named sidebar (unless the name changed in the config), into the root or the namespace you want, and put among other contents an {{indexmenu}} tag into it. It has a lot of options, so check the documentation.
Note that there is also a rightsidebar for some templates.

including a header from a project into a static library

I have a subproject (static library) inside my project.
As this static library may be used by a bunch of app, I have this config.h file on my project that contains the app configuration. The static library must read it.
The problem is that adding
#import "config.h"
on the static library fails, because the file cannot be found.
I could add an absolute path to my project root on the search headers, but I want to make this not hard coded because this static library will be used by other projects. Another problem is that I cannot use relative links like ../.., for example, because the static library is on another volume.
Including $(SRCROOT) on the search paths of the static library will give me the root for that library not for the project using it, that is what I want.
How do I solve that?
Just pay attention to my question. I am inside a static library that is used by a project. Config.h is out there in the project. I want to import that config.h on my static library.
If there is an easy way to do that, please tell me.
I have uploaded a sample project to here and here, so you can see my pain.
thanks
One way, somewhat of a hack, is to add a Run Script to each App's Build Phase, as the first item, and have it copy Config.h to some known place - /tmp/Config.h, and your included library will look for it there. Since the file is copied on every build, it will always be proper.
EDIT1: So not pretty, but you can add a Run Build Script to just under the Dependencies in the library. Just add one and leave the checkbox set to show environmental variables. You can see this one set:
FILE_LIST=/Volumes/Data/Users/dhoerl/Library/Developer/Xcode/DerivedData/MyProject-fdzaatzqtmrnzubseakedvxmsgul/Build/Intermediates/MyStaticLibrary.build/Debug-iphoneos/MyStaticLibrary.build/Objects/LinkFileList
What you can see is that several of these have as the prefix the current project folder:
/Volumes/Data/Users/dhoerl/Library/Developer/Xcode/DerivedData/MyProject-
You can write some script there to get the prefix, then append the local Config.h file path, and now you have a fully qualified path to the Config.h header, which you can then copy to a known location in the library. I'm going to post on the xcode forum as there may be a better solution - there use to be in Xcode 3. I'll update this if I get anything substantive back.
EDIT2: Try This:
1) Click on the library, click on Build Phases, add a Run Script Build phase by tapping bottom right '+' button
2) Drag it so its the second item in the list (below Target Dependencies)
3) Change the Shell to "/bin/ksh"
4) Paste this in, after editing it to have the proper files/paths:
# Get the Project Name (assumes upper/lower/numbers only in name)
PROJ=$(echo $BUILD_DIR | sed -En -e 's/(\/.*\/)([A-Za-z0-9]+)-([a-z]+\/Build\/Products)/\2/p')
# Use this variable to construct a full path
FULL_PATH="/Volumes/Data/Users/dhoerl/Downloads/nightmare/"$PROJ"/"$PROJ"/HelloWorldLayer.h"
echo FULL_PATH equals $FULL_PATH
# Make Sure MyStaticLibrary is correct
echo PROJ_DIR equals "$PROJECT_DIR/MyStaticLibrary"
cp -f "$FULL_PATH" "$PROJECT_DIR/MyStaticLibrary"
5) This assumes that you put the library anywhere you want, but each App project has to havethe same parent folder (not much of a restriction - what I did in the past).
PS: When I do this kind of thing, I usually don't include an actual file of the app, but create a header for a class that is not instantiated in the library. Lets call this Foo. So in your library, you have Foo.h, and it has lots of methods that return info - the number of widgets, the location of some special folder, plists, arrays, dictionaries, whatever. The idea is the library knows how to get whatever it needs through this interface (class singleton, or just a class with class methods. YMMV.
PSS: anyone else reading this, it pays to create demo projects.
I'd go a different route. Make this config.h file part of the static library using compiler symbols in it to switch features. Then in your projects define those symbols depending on what features you need.

Change a localized InfoPlist.strings using an Xcode target

Here's an obscure problem. I'm using an InfoPlist.strings to localize my app name. It's only got one value: CFBundleDisplayName = "Mon App". The strings file is localized (putting it in a directory for that localization).
I've just made an extra target, where I change things like the non-localized app name (different Info.plists), and the icon. I'm also changing the Default.png using a run script build phase (copying different files depending on the app type I'm building).
I've tried using the script to copy different versions of my InfoPlist.strings, but I couldn't make it work. Here's what I used:
if($TARGET_NAME == "MonApp")then
cp fr.lproj/MonApp_InfoPlist.strings fr.lproj/InfoPlist.strings
endif
I've seen a post suggesting wincent strings util for processing strings, but wanted to see if there's an easy way to do this. Any help greatly appreciated.
You don't need to do this.
If you have fr.lprog/InfoPlist.strings and en.lproj/InfoPlist.strings in your project, you should see just one InfoPlist.strings entry, with two subitems fr and en. If you drag and drop the InfoPlist.strings file into a Copy Bundle Resources build phase, all localized versions will be copied into the appropriate .lproj files at build time. You don't need to create a separate target or write a script to do this; the right thing happens.