Asset Catelog issue with multiple targets - ios

I have a project with multiple targets. Assume the targets are named Target-A, Target-B and so on. For every target I have a different asset catalog of App Icons. They are named as AppIcon - A, AppIcon - B and it goes on for all the targets. I have assigned respective asset catalogs to all targets, but it only shows the icons for Target-A when i run on the device / simulator. For all other targets it does not set any icons and shows iOS 7 default placeholder icon.
Please help!

If you're using PODs in your project, then you have to edit "Pods-resources.sh" and remove "xcassets" commands (see attached picture).

When you are adding the app icon image please note while adding app icon-1 to Test target then select only test target not Test copy target same for Test copy target.
Also add row for "Icon file" in both the plist and specify your app icon names.
Please check following screen shots you will get some ideas.

The easiest way for me was to add multiple "App Icon" in the same xcassets file. With this technique, I had no problem with Cocoapod :
Open your xcassets file
Right click on the left column
Click "New App icon"
Then you can easily select the correct "App Icon" for each target.

So I wrote a script to delete all those lines which are pointed out by Lukapple.Paste the code to run Script in the xcode project after Target Dependencies.
echo "run script to remove Pods-resources.sh"
file_name="${PROJECT_DIR}/Pods/Target Support Files/Pods/Pods-resources.sh"
function remove_wrapper_extensions {cat "$1" | awk 'BEGIN { suppress_output = 0; } /^if \[\[ -n/ { suppress_output = 1; } (!suppress_output) { print $0; } /^fi$/ { suppress_output = 0; }' > "${1}.1"}
function remove_case_statement {cat "$1" | awk 'BEGIN { suppress_output = 0; } /\s*\*\.xcassets\)$/ { suppress_output = 1; } (!suppress_output) { print $0; } /;;/ && (suppress_output) { suppress_output = 0; }' > "${1}.2"}
remove_wrapper_extensions "$file_name"
remove_case_statement "${file_name}.1"
rm "${file_name}"
rm "${file_name}.1"
mv "${file_name}.1.2" "$file_name"
chmod +x "${file_name}"

Related

Xcode 8 Beta - Convert to Current Swift Syntax Failed: Could not find test host

I am receiving an error message when I try to use Xcode 8's Convert Wizard.
After trying rebooting, downloading fresh code, and deleting my DerivedData files I cannot escape this error:
Convert to Current Swift Syntax Failed: Could not find test host
I have tried both options which are: Swift 2.3 and Swift 3. After I select a version I instantly get that error.
Here is a screenshot of the error:
This worked for me:
Select the Xcode project in the lefthand browser.
Click on your test target in the Project's General tab.
Disclose "Testing". In my project the "Host Application" pulldown button was blank. Select your appropriate host application.
Try building your test target now. If that succeeds then converting syntax should as well.
I had this problem after installing the Xcode 8 beta so I assume this is related.
Picture Credit to #karthikkck
It cost me a bit of time to find the "Host Application" pulldown mentioned in the otherwise very helpful answer by iluvcapra.
So this is what he meant:
This is where you find the pulldown menu. Select your main target.
I find easy fix for this, just edit your Scheme and disable tests.
And run conversion again.
+1 iluvcapra
Alternatively, use text editor to remove the following two items from your MyAppSwift.xcodeproj/project.pbxproj file, search for TEST_HOST
Now, re-open your project and run the convert wizard again.
4EFFFAE51B53D5D8003CD25A /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
);
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
INFOPLIST_FILE = "AF SwiftTests/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) #executable_path/Frameworks #loader_path/Frameworks";
PRODUCT_NAME = "FA SwiftTests";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AF Swift.app/AF Swift";
};
name = Debug;
};
4EFFFAE61B53D5D8003CD25A /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
);
INFOPLIST_FILE = "AF SwiftTests/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) #executable_path/Frameworks #loader_path/Frameworks";
PRODUCT_NAME = "FA SwiftTests";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AF Swift.app/AF Swift";
};
name = Release;
};
Please try these Steps:
Select your project on the left side of Xcode.
Go to Targets and select your Project Tests.
Select the General Tab and select Host Application drop down and choose your Host Application.
Convert or Run your project.
Trying these steps worked for me.
In my case I deleted my tests target, then re-added it using the + below targets and selecting "iOs Unit Testing Bundle"
For some reason this got a compile error, so I changed the "Per-configuration Intermediate Build Files Path: for my test target to $(PROJECT_TEMP_DIR)/$(CONFIGURATION) for both debug and release. This allowed the compile to work.
Fix this in 3 steps:
First delete your test target
The select Edit -> Convert -> To current Swift syntax... and perform the conversion
Then add a new test target

How do I display the CFBundleShortVersionString in my LaunchStoryboard?

Is there any way to display the CFBundleShortVersionString as a UILabel text in my LaunchStoryboard without entering it by hand every time it increments? I know how to do it in code, but it is not possible to run code while the LaunchStoryboard is shown.
Is it possible through Xcode variables?
As we all know, you can't put code in a launch screen. And unfortunately there isn't a built-in way to use a variable for a label's text in the launch screen (similar to how you can preprocess Info.plist with values in a header file).
The only option available to achieve your goal would be to write your own script that updates the LaunchScreen.storyboard file and add that script as a custom Build Phase for your target.
To make this easier, I would setup your target to use a preprocessor file for Info.plist. Once that is done and working, you now have a separate and simple header file you can interrogate in your script to process the LaunchScreen.storyboard file.
Here's a complete solution:
Create a file named Info.h and add it to the root of your project.
Add the following line:
#define APP_VERSION 2.6 // Update this version as needed
Now select your project's target in Xcode and go to the General tab. Change the Version value from whatever number you have there to APP_VERSION.
Now select the Build Settings tab. Search on Info. Under the Packaging section, set the Preprocess Info.plist File to Yes. Also set the Info.plist preprocessing Prefix File to Info.h.
Now when you do a build, the CFBundleShortVersionString value in Info.plist will be set to the value in the Info.h file.
To get the label in the launch screen file updated to match, do the following:
Select your launch screen storyboard and then select the label that will contain the version number. Show the Identity Inspector pane. Enter APP_VERSION into the Label attribute. If you look at the storyboard file now, the XML for the label will now show a userLabel attribute with the value of APP_VERSION.
Go back to the project target and select the Build Phases tab. Click the + icon and choose to add a New Run Script Phase. Rename the new phase to something useful like "Update Launch Version". Then drag the new phase to before the existing "Copy Bundle Resources" phase.
Now open the new "Update Launch Version" phase. Enter /bin/bash in the Shell field. Copy and paste the following code into the phase:
VERSION=`cat Info.h | grep APP_VERSION | cut -f3 -d' '`
sed -e "/userLabel=\"APP_VERSION\"/s/text=\"[^\"]*\"/text=\"$VERSION\"/" Storyboard.storyboard > tmp.storyboard
Now do a clean build. This is a test at this point. Have a look at tmp.storyboard and make sure it looks correct and the label for the app version is showing the proper version.
Once that is working, update the above code to:
VERSION=`cat Info.h | grep APP_VERSION | cut -f3 -d' '`
sed -i bak -e "/userLabel=\"APP_VERSION\"/s/text=\"[^\"]*\"/text=\"$VERSION\"/" Storyboard.storyboard
This final version actually updates the launch screen storyboard file. The previous version was a test to make sure everything else was working without risk to trashing your storyboard.
I figured out the script to update the Version & Build label on LaunchScreen.storyboard based on the first answer without using any extra files. Unfortunately, Clemens Brockschmidt's solution doesn't work due to some Syntax errors and incorrect paths.
Make sure to name your label to "APP_VERSION" in Identity Inspector pane -> Document -> Label.
Also create your script before "Copy Bundle Resources" phase.
UPDATE: My older answer didn't work in the newest Xcode environment. I've fixed the current issues and refactored the script.
And here's the final working script with shell: /bin/sh in XCode 11 (Swift 5):
# ON/OFF Script Toggle (script ON with #, script OFF without #)
#exit 0
# Increment Build Number Bool (Increment ON with true, increment OFF with false)
shouldIncrement=false
# App vesion / Build version constants
sourceFilePath="$PROJECT_DIR/$PROJECT_NAME/Base.lproj/LaunchScreen.storyboard"
versionNumber="$MARKETING_VERSION"
buildNumber="$CURRENT_PROJECT_VERSION"
# Increment build number
if [ "$shouldIncrement" = true ]; then
buildNumber=$(($buildNumber + 1))
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "$INFOPLIST_FILE"
fi
# Output version & build numbers into a label on LaunchScreen.storyboard
sed -i .bak -e "/userLabel=\"APP_VERSION\"/s/text=\"[^\"]*\"/text=\"$versionNumber($buildNumber)\"/" "$sourceFilePath"
As a BONUS I've included a build number incrementer and ON/OFF script toggle to disable your incrementer when you build your project a lot. Let me know if you have any issues or if this works for you.
Edit
There is no way to make the launch screen dynamic. Doesn't work good
with localizations too etc
A alternative is given below
Previous Answer
You should make your inital VC similar to the LaunchScreen.xib and in that make a label.
Now in the ViewController you can access the info plist through NSBundle method and set its value. This would make the transition from Launch screen to first VC smooth and look natural with version code animating in or something if you want
let appVersion = NSBundle.mainBundle().infoDictionary["CFBundleVersion"];
myLabel.text = "\(appVersion)"

Change all image names except app icon build phase xcode

I am working on an ipad project that requires changing the formatting of image names for the project in a run script build phase in xcode 5. I am running the following script:
for f in ${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}/*.png
do
fileName=${f:${#BUILT_PRODUCTS_DIR}+${#FULL_PRODUCT_NAME}+2:${#f}}
lc='echo $fileName | tr "[:upper:]" "[:lower:]"
lc=`echo $lc | tr - _`
lc=${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}/${lc}
mv $f $lc
done
The script finds all images in the bundle and makes the names all lowercase and changes uses of '-' to '_'. This works perfectly for my situation, however it is also changing the name of the app icon and launch images resulting in them not being used by the app.
What I want is either a way to have the script skip the app icon and launch images, or a way to simply change the names of the images in xcode so that the resulting name from the script is the accurate name.
The biggest issue I have had with simply manually changing the names is that I cannot find how xcode is controlling the naming system because the names I have for the images are already in the proper format so xcode must be creating its own names for the icon and launch images.
Thanks
Assuming standard naming, and that you don't also have your own files that begin with "Icon" or "Default", you could do this. If you have your own images that match that pattern, you will need to add special cases below, or specifically target all the various icon and launch image files.
for f in ${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}/*.png
do
BASENAME=$(basename $f)
if [[ ${BASENAME} == Icon* ]] || [[ ${BASENAME} == Default* ]] ;
then
echo "App icon or launch image, leaving file alone"
else
fileName=${f:${#BUILT_PRODUCTS_DIR}+${#FULL_PRODUCT_NAME}+2:${#f}}
lc=`echo $fileName | tr "[:upper:]" "[:lower:]"`
lc=`echo $lc | tr - _`
lc=${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}/${lc}
mv "$f" "$lc"
fi
done

How to open .xcodeproj programmatically?

I have projects called A.xcodeproj, B.xcodeproj, C.xcodeproj
now what is question, in AppDelegate of Project A , open project B and C on condition.
int run;
run = 0;
if(run == 0)
{
Open project B.xcodeproj
}
else
{
Open project C.xcodeproj
}
Help
Thanks in Advance.
on the command line use open to OPEN and SHOW xcode.. so in your case, when run == 0
when you want to BUILD the xcode project, invoke xcodebuild instead of open!..so in your case, when run == 1

Qt / QMake iOS Set Target, Device, other XCode settings

Qt for iOS creates an XCode project when you execute a build.
How does one dictate the XCode project settings from Qt to set a "target" (minimum iOS version) and "device" (Universal/iPhone/iPad), as found on the "General" tab in XCode when this project is opened?
I could not find this documented anywhere, but I figured it out.
In your qmake (pro or pri file) add these lines:
# Set "Target"
QMAKE_IOS_DEPLOYMENT_TARGET = 5.0
# Set "Devices" (2=iPad Only)
QMAKE_IOS_TARGETED_DEVICE_FAMILY = 2
Note for devices: 1=iPhone, 2=iPad, 1,2=Universal.
If you need to change other XCode project settings here's how you can:
After a build in Qt for iOS look at the "Compile Output" tab.
You will find a list of "export VARIBALE=some_value" entries.
To change one of these XCode build settings, simply use QMAKE_IOS_VARIABLE_NAME = my_value in your qmake.
For more info on these environmental varibles, check this out: Xcode Build Setting Reference
-- UPDATE --
I was wrong about the last part. You can't set all the XCode variables quite like that. If you output QMAKESPEC, however, you will get the path where you can find a qmake.conf file which will display some of these undocumented variables. Do so like this in your pro / pri:
message( $$QMAKESPEC )
That path will appear in the Qt console "General" tab when you build the project.
Here's an extended version I'm now using, with some logic for setting the build architectures:
greaterThan( QT_MAJOR_VERSION, 5 ){
DEFINES += QT_VER_5_4_OR_NEWER
}
else:equals( QT_MAJOR_VERSION, 5 ) &&
greaterThan( QT_MINOR_VERSION, 3 ){
DEFINES += QT_VER_5_4_OR_NEWER
}
contains(DEFINES, QT_VER_5_4_OR_NEWER){
DEFINES += SUPPORT_64_BIT_IOS
message( "SUPPORT_64_BIT_IOS" )
}
contains(DEFINES, SUPPORT_64_BIT_IOS) {
iosArchitectures="armv7 arm64"
iosTarget=5.1.1
}
else{
iosArchitectures=armv7
iosTarget=5.0
}
# Set "Architectures"
QMAKE_IOS_DEVICE_ARCHS = $$iosArchitectures
# Set "Target"
QMAKE_IOS_DEPLOYMENT_TARGET = $$iosTarget
# Set "Devices" (1=iPhone, 2=iPad, 1,2=Universal)
QMAKE_IOS_TARGETED_DEVICE_FAMILY = 2

Resources