Is there a way to share Xcode templates across a team? - ios

At work, we've been moving towards a VIPER based architecture, so I have written an Xcode template for creating and instantiating all the required files which works perfectly for what we need.
I have pasted it ~/Library/Developer/Xcode/Templates, and it works and shows up fine, however I've been asked to look into if it was possible to have it synced across the team instead of having to email it to everyone whenever there is a change, or reuploading to Confluence and having everyone redownload and reinstall it. Now, I've looked online, but I am unable to see anything of much help about syncing them across team members, so I just thought I'd ask if you guys know of a way?
Thanks a million guys

I have the same thing on my project and all I did was to add the template files on the source control (into a separated folder) and write a shell script to install/uninstall the templates:
Note that it uses symlink so any updates will propagate.
#!/usr/bin/env bash
set -eo pipefail
# Default the folder name to "Project Name".
folderName="Project name that will show under Xcode Menu"
scriptPath="$( cd "$(dirname "$0")" ; pwd -P )"
xcodeTemplateDirectory=~/Library/Developer/Xcode/Templates/File\ Templates/
linkName="$xcodeTemplateDirectory"/"$folderName"
if [ $1 == "install" ]; then
# Create the install directory if it does not exist.
if [ ! -d "$xcodeTemplateDirectory" ]; then
mkdir -p "$xcodeTemplateDirectory"
fi
rm -rf "$linkName"
ln -s "$scriptPath"/"$folderName" "$xcodeTemplateDirectory"
fi
if [ $1 == "uninstall" ]; then
rm -rf "$linkName"
fi

Related

My .framework doesn't seem to be generated

I'm currently trying to maintain a library that was written internally in order to update our cocoaPods repository. In order to do that I've got to be able to get the .framework that's supposed to be generated when i build the library (I guess, I'm more than new to the the entire Xcode/iOS world)
I found the build phase menu where I found a submenu called "Prepare Framework" I guess it's here that everything is going on ..
Here is what's there:
set -e
mkdir -p "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework/Versions/A/Headers"
# Link the "Current" version to "A"
/bin/ln -sfh A "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework/Versions/Current"
/bin/ln -sfh Versions/Current/Headers "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework/Headers"
/bin/ln -sfh "Versions/Current/${PRODUCT_NAME}" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework/${PRODUCT_NAME}"
# The -a ensures that the headers maintain the source modification date so that we don't constantly
# cause propagating rebuilds of files that import these headers.
/bin/cp -a "${TARGET_BUILD_DIR}/${PUBLIC_HEADERS_FOLDER_PATH}/" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework/Versions/A/Headers"
The thing is when I build the library, I never find the .framework I do need ..
I think there might have an error on that side. If you guys could help me..
Guillaume :-)
The problem lies with the last line of your script
/bin/cp -a "${TARGET_BUILD_DIR}/${PUBLIC_HEADERS_FOLDER_PATH}/" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework/Versions/A/Headers"
There's either supposed to be a backslash there, or you should write the path in single line (inside the same set of double quotes)
/bin/cp -a "${TARGET_BUILD_DIR}/${PUBLIC_HEADERS_FOLDER_PATH}/" \
"${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework/Versions/A/Headers"
or
/bin/cp -a "${TARGET_BUILD_DIR}/${PUBLIC_HEADERS_FOLDER_PATH}/${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework/Versions/A/Headers"

How to stop Fabric from running

I've went through documentation: http://support.crashlytics.com
It doesn't seem to question the purpose of the app, so I will ask here :)
I have Fabric integrated in my app. As per installation process, I've installed Fabric app on the Mac I am working on.
Now, from time to time, I have Fabric app that keeps opening, which I personally find very annoying. It's too much for a 3rd party service (even for a great one as Fabric Analytics).
In the build steps in Xcode I've found a script, but doesn't seem that it does the thing:
#!/bin/sh
# run
#
# Copyright (c) 2015 Crashlytics. All rights reserved.
# Figure out where we're being called from
DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
# Quote path in case of spaces or special chars
DIR="\"${DIR}"
PATH_SEP="/"
VALIDATE_COMMAND="uploadDSYM\" $# validate run-script"
UPLOAD_COMMAND="uploadDSYM\" $# run-script"
# Ensure params are as expected, run in sync mode to validate
eval $DIR$PATH_SEP$VALIDATE_COMMAND
return_code=$?
if [[ $return_code != 0 ]]; then
exit $return_code
fi
# Verification passed, upload dSYM in background to prevent Xcode from waiting
# Note: Validation is performed again before upload.
# Output can still be found in Console.app
eval $DIR$PATH_SEP$UPLOAD_COMMAND > /dev/null 2>&1 &
So what is Fabric App is really for? Can it be excluded from the workflow? Can I actually erase it and continue the management through Pods? What's the trick behind it?
Because this question is still relevant, to prevent Fabric from launching, you got two options:
1. Stop it after uploading your project’s DSYM file.
Open up the run script: Pods/Fabric/run and change:
eval $DIR$PATH_SEP$UPLOAD_COMMAND > /dev/null 2>&1 &
To:
eval $DIR$PATH_SEP$UPLOAD_COMMAND;killall Fabric > /dev/null 2>&1 &
2. Stop it and only upload DSYM when archiving builds for release:
Check the “Run script only when installing” option under Build Phases:

Script to generate Xcode empty project

I always need some empty Xcode projects for testing purposes. (I cannot use coderunner or other stuff, I really need an Xcode project).
I tried different approaches but I didn't find a real solution:
Created a basic, empty project and created a script for copying the entire folder.
It works, but you cannot have different names for the project, this means that you have to rename the project manually after the copy.
Using the Crafter gem
It's a useful gem, but you can only configure an existing project, you cannot create a new one.
Using KZBootstrap
The same as before, it's useful for configuring the project, not for creating a new one.
Using the xcodeproj gem (http://rubygems.org/gems/xcodeproj)
The documentation is not enough for me, and I don't understand how to use it :(
Any advice?
Finally i found a solution that fits my needs.
I started with an empty, sample project (here https://dl.dropboxusercontent.com/u/792862/SamplePRJ.zip)
and i wrote a bash script to rename all the files and all the occurrences of the previous name.
The script can be improved, but it basically works
export LC_CTYPE=C
export LANG=C
OLDNAME="SamplePRJ"
NEWNAME="Sample2PRJ"
mv $OLDNAME $NEWNAME
cd $NEWNAME
mv $OLDNAME $NEWNAME
mv ${OLDNAME}Tests ${NEWNAME}Tests
mv ${OLDNAME}.xcodeproj ${NEWNAME}.xcodeproj
mv ${NEWNAME}.xcodeproj/xcshareddata/xcschemes/${OLDNAME}.xcscheme ${NEWNAME}.xcodeproj/xcshareddata/xcschemes/${NEWNAME}.xcscheme
find . -type f -print0 | xargs -0 sed -i '' "s/${OLDNAME}/${NEWNAME}/g"

Xcode 5 bots and Testflight automated builds

First I have a Mac Mini running Server on Mavericks and have Xcode 5 installed. On the server I have my iOS projects set up with Bots to run automated builds of my Github repo on each commit to master. What I want to find out is if anyone already has configure this kind of setup to work with automated builds being sent to TestFlight.
The script that worked previously with a Jenkins build process is pasted below, but throws an error and doesn't upload when the bot completes it's build. I have this script run on the "post-action" of the archive process of my app.
Server log error:
Print: Entry, "CFBundleVersion", Does Not Exist
error: Specified application doesn't exist or isn't a bundle directory : '/Library/Server/Xcode/Data/BotRuns/Cache/s892fj1n2-f4bb-2514-522v-2a23d0f0c725/DerivedData/Build/Products/Debug-iphoneos/myApp.ipa'
Script:
PLIST_FILE=$(echo -n "${SRCROOT}/${INFOPLIST_FILE}")
BUILD_TYPE=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "${PLIST_FILE}")
API_TOKEN="<API_TOKEN>"
TEAM_TOKEN="<SECRET>"
APP="${BUILD_ROOT}/Debug-iphoneos/${FULL_PRODUCT_NAME}"
/bin/rm "/bots/${PRODUCT_NAME}.ipa"
/usr/bin/xcrun -sdk iphoneos PackageApplication -v "${APP}" -o "/bots/${PRODUCT_NAME}.ipa"
/usr/bin/curl "http://testflightapp.com/api/builds.json" \
-F file=#"/bots/${PRODUCT_NAME}.ipa" \
-F a pi_token="${API_TOKEN}" \
-F team_token="${TEAM_TOKEN}" \
-F notes="Build uploaded automatically from server." \
-F distribution_lists="internal"
UPDATE 11/20:
A good resource to try:
TestFlight Bots
I didn't get it to work a couple weeks ago but the post has been updated since I last tried.
This looks like a permissions issue. Are you able to access \Library\XCode\Data folder? I was able to run your script (other than upload to testflight). I had to give read access to \Data and write access to destination folder and I see the ipa created.
I am researching ways to switch my team from our Jenkins farm for iOS builds to the new Xcode bots server. I have a very similar problem to solve regarding continuous deployment upon a successful CI build/test.
I don't have an answer (yet), but, wanted to share some things I found that may help you.
Two threads may help give clues to why your TestFlight upload is failing on the bots server.
According to Kra Larivain with this post regarding the CocoaPods CLI and Xcode bots:
"the build runs on the bot as an unprivileged user with no shell (_teamsserver with /usr/bin/false as a shell)"
"add _teamsserver to the password-less sudoers (%_teamsserver ALL=(ALL) NOPASSWD: ALL in your sudoers file). You probably want to be a little bit more clever and only grant it sudo privilege" for the commands actually needed
/Library/Server/Xcode/Data is set to be rw by the _teamsserver user only
"add to your pre action the following script, where BUILD_USER is your, well, build user. Make sure you Provide build settings from the main target, SRCROOT won’t be set otherwise (the default is None)." This example is for CocoaPods, but, could be adapted to your use
if [ `whoami` = '_teamsserver' ]; then
echo "running pod install as part of CI build"
chmod 777 /Library/Server/Xcode/Data
cd ${SRCROOT}
rm ./Podfile.lock
rm -rf ./Pods
sudo chown -R BUILD_USER .
sudo -H -u BUILD_USER pod install
sudo chown -R _teamsserver .
fi
You likely seen this already, but, it's worth mentioning for others. Check Justin Miller's post on Xcode and testflight post-archive actions for comparison with your script.
Good luck!
Steve

Creating Cydia Logos Tweak, now required respring after installation (How to do)

I am creating a Logos Tweak for Cydia and i did complete my task, but now i required "Restart SpringBoard" after Installation.
Can anybody tell me what i have to do to achieve this like many apps in Cydia store, In which after installation button appears with text "Restart SpringBoard" instead of "Return to Cydia".
You could do this 2 ways if you are using THEOS,
First one (if you do make clean then you will have to redo these steps),
Create 2 files in the DEBIAN folder which is located in mytweak/_/DEBIAN/
Call them preinst and postrm
Inside those files paste:
declare -a cydia
cydia=($CYDIA)
if [[ $1 == install || $1 == upgrade ]]; then
if [[ ${CYDIA+#} ]]; then
eval "echo 'finish:restart' >&${cydia[0]}"
fi
fi
exit
Then run make package to create the new package that has the respring button on it
The second way is much more simpler and can be used without theos,
In the control file which is located in the DEBIAN folder, you should know where this is.
Add the line:
Depends: mobilesubstrate
Credit to Nate for this answer, although I did know this.
Hope this helped.

Resources