Clone an Xcode Project

I’ve got a couple of projects on the go right now, but one of the more interesting ones is a script that walks a user through the process of cloning an Xcode project and do some variable substitutions. With the final result being an iOS app that is ready to submit to the App Store.

The reason for this project is that one of my app platforms lends itself to being very niche specific and it makes sense to go for a bunch of targeted niche apps rather than a few all encompassing ones. To that end I wanted a way to quickly take the app platform to as many niches where it makes sense. To do it in a reasonable amount of time required some automation.

The approach I’ve taken is to generate a master app. The code in the master app has some placeholder variables which I can easily do search and replace. Along with that I found a script to copy and rename an xcode project which deals with the xml files and folder names and such. The script to rename the project itself is from http://rudifa.wordpress.com/2011/07/23/clonexcodeproject-sh/.

One of the helpful things about this script is that by using PIL I can easily scale the images in the project down from the retina source graphics. I can walk myself through all the tedious stuff like getting provisioning profiles, setting up Facebook and Twitter keys so that I don’t forget to do things or do them in the wrong order.

It would be easy to see how this could be extended. Perhaps by adding a few more variable substitutions it would be easy to add/remove various features by setting pre-processor flags or tweak behaviours like, speeds, timeouts etc. Wrapping it all into a nice GUI would make this whole thing into a drag and drop app creator tool that anyone could use.

#!/usr/bin/env python
 
#######################################
#
# Written By Matt Warren, Halotis Inc.
# http://halotis.com
# http://mattwarren.co
#
# This script is a wizard to walk you through duplicating an Xcode project that
# follows the patterns I've done for my previous projects.  It's not meant to
# be completely generic.
#
#######################################
 
import subprocess
import zipfile
from PIL import Image
import glob, os
 
def main():
    """
    the script asks questions and then unzips, renames and runs some variable substitions
    on the AppDelegate.h file.  the final product should be ready to test and submit
    """
 
    #These are in no particular order...
    print """
################################################################################
 
MATTS SUPER AWESOME PROJECT MULTIPLIER WIZARD!!!
 
Fear not about making mistakes.  All these values can be easily fixed in the final project.
Just fill things out as best you can and fix missing values during testing.
 
This script requires a file called SampleProject.zip which contains a project called SampleProject
 
The process is:
    1. create/rename the Xcode project
    2. Create the art assets and put them in place
    3. Tie the app to various services and set up in iTunesConnect
    4. replace constants in AppDelegate.h
    5. Test
    6. Upload binary to Apple
    7. Profit!!
################################################################################
    """
    new_app_name = raw_input('Please enter New App Name:')
    new_proj_name = new_app_name
 
    raw_input('Renaming SampleProject to %s (enter to continue)' % new_proj_name)
    print 'Thanks, unzipping and renaming base project...'
 
    z = zipfile.ZipFile('SampleProject.zip')
    z.extractall('./')
 
    result = subprocess.call(['./RenameXCodeProj.sh', 'SampleProject', new_proj_name])
 
    if result != 0:
        print 'FAILED TO RUN RENAME SCRIPT'
        return
 
    print 'On to the Art...'
 
    garbage = raw_input(' ## OVERWRITE %s/Default@2x.png (enter to continue) ##' % new_proj_name)
    image = Image.open('%s/Default@2x.png' % new_proj_name)
    small_image = image.resize((image.size[0] / 2, image.size[1] / 2), Image.ANTIALIAS)
    small_image.save('%s/Default.png' % new_proj_name)
 
    garbage = raw_input(' ## OVERWRITE %s/Default~ipad@2x.png (enter to continue) ##' % new_proj_name)
    image = Image.open('%s/Default~ipad@2x.png' % new_proj_name)
    small_image = image.resize((image.size[0] / 2, image.size[1] / 2), Image.ANTIALIAS)
    small_image.save('%s/Default~ipad.png' % new_proj_name)
 
    garbage = raw_input('Create Icons using PhotoShop template, (enter to continue)')
 
    print 'variable subsitutions are next:   (avoid using anything with quotes)'
 
    header_content = open('%s/Classes/AppDelegate.h' % new_proj_name, 'r').read()
    header_content.replace('<app_name>', new_app_name)
 
    website = raw_input('Please enter App Website:')
    header_content.replace('<website>', website)
 
    print 'http://itunesconnect.apple.com'
    apple_app_id = raw_input('Apple App ID:')
    header_content.replace('<app_id>', apple_app_id)
 
    print 'https://developers.facebook.com/'
    facebook_app_id = raw_input('Facebook App ID')
    header_content.replace('<facebook_app>', facebook_app_id)
 
    print 'http://dev.twitter.com/apps/new'
    twitter_consumer_key = raw_input('Twitter Consumer Key (use website above for callback)')
    header_content.replace('<twitter_consumer>', twitter_consumer_key)
 
    twitter_secret = raw_input('Twitter Secret')
    header_content.replace('<twitter_secret>', twitter_secret)
 
    print 'configure Facebook App ID in URLS - DO THIS MANUALLY!!'
 
    print 'Writing new App Delegate Header File'
    with open('%s/Classes/AppDelegate.h' % new_proj_name, 'w') as header:
        header.write(header_content)
 
if __name__ == '__main__':
    main()
</twitter_secret></twitter_consumer></facebook_app></app_id></website></app_name>