Reputation: 899
I have a project where I need to build some apps out of one Basic App. For "Sub-Apps" it changes the API-Credentials, Fonts, Sizes, Colors and some features of the App.
So I changed my App that I can easily add features, change colors, ... by changing simple String constants to build new Apps faster.
I thought that the best solution would be to add multiple Targets to this XCode Project and set the individual Settings of the App with Conditional Compiler flags
#ifdef AppTarget1
qr_reader = YES;
#endif
But the Problem is, that in future will be available multiple versions of the Framework. So when updating an App based on a old Framework we always had to do the adjustments to work with the new Version of the framework (if any) and we've no control over the Framework Versions, ect.
One goal is also to allow our Developers with a Simple Podfile build new Apps easily.
So the next idea was to create a Framework Project, what then is included with CocoaPods in our Main Apps. I followed this tutorial: http://chariotsolutions.com/blog/post/using-cocoapods-to-manage-private-libraries/
In the MainApp I included the Framework, the MainApp-AppDelegate Class is a Subclass of the Framework-AppDelegate Class.
@interface MainApp_AppDelegate : FrameworkAppDelegate
The Method where I set all the App-Based Settings I overwrite in the MainApp_AppDelegate.
@implementation MainApp_AppDelegate
-(void)initSettings {
qr_reader = YES;
}
@end
It worked like a charm, but one Problem I've with images. The AppFramework contains Image training.png and image y.png.
In the Main App xyz I decide that the Image training.png looks not good for this App, so I want to change only that (y.png I want the version included in the Framework). I put the x.png into the Main App Ressources Folder, but after compiling and Running there I see the Image included in the AppFramework Project.
Are there any ways to change that behaviour or better ways to create a Framework?
Upvotes: 2
Views: 395
Reputation: 11016
What is happening is Cocoapods copies its resources in the final .app
bundle after your app is done copying his. So your training.jpg
gets overwritten by your framework's.
As @masam said, you need to reorder the build phases of your project in order to copy your app's resources after Cocoapods' resources.
(Notice how "Copy Bundle Resources" is now under "Copy Pods Resources" in the list)
Unfortunately, this will not be sufficient, as Xcode's build system is (tries to be?) smart and will not copy (or recompile in the case of a source file) a target which is "up-to-date". For a static resource like an image, being up-to-date means that the target path (in the final .app
bundle) is newer than the source path (in you Xcode project).
So if you try to run your app now, you will notice no change. Xcode won't copy the training.jpg
as it is already present and newer in the .app
.
You will need to trick Xcode into thinking that the resources in the .app
are outdated and needs to be updated. To do this, add a new "Run Script Build Phase" between "Copy Pods Resources" and "Copy Bundle Resources":
The script should set the modification date of the resources to an earlier date, to force Xcode to copy your app's resources. touch
does the job:
find ${TARGET_BUILD_DIR} -name 'training.jpg' -exec touch -ct $(date -v-1d "+%Y%m%d%H%M.%S") {} \;
We use date -v-1d "+%Y%m%d%H%M.%S"
to set the resource's modification date to yesterday.
Xcode will now overwrite the framework's image with the app's one.
Again, as @masam said, don't forget to add the resource only to correct targets.
eg.
Here, the app image will be used in DummyApp, but DummyApp2 will use the framework image.
tl;dr: Avoid this if possible.
find
more inclusive, eg. find ${TARGET_BUILD_DIR} -name '*.png'
);On the one-target-per-app-flavor thingy:
Remember that each modification you make on one target's Build Phases will NOT impact other targets Build Phases. You'll need to edit every targets individually. Hence my previous don't do it if you can avoid it.
I perfectly understand the need to have multiple targets to build multiples apps based on the same codebase, but Xcode is horribly bad at managing a large number of targets. Take it from a guy currently working on an fairly large app (1k+ files, and a lot of dependencies) with 65 different targets: this is a nightmare.
The .pbxproj
will basically grow in factor of your number of targets (25MB in my case), and you'll get the beach ball each time a project modification in done in Xcode. And as each target is managed independently, each time you need to eg. add/remove a compile flag, you will need to update each target, one. by. one. (or you will edit the .pbxproj
"by hand" with sed
/awk
/whatever, which is faster, but risky... but fun :)).
Oh... and did I mention merge conflicts?
Upvotes: 2
Reputation: 399
duplicate your targets !?
The last apps I build by this way were using a different bundle identifier for each target. Then just have a test to you bundle ID to make your different settings programmatically.
NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
Upvotes: 0
Reputation: 2278
This might be due to a certain order in your build phases (Project -> Build Phases). Default, it will copy the bundle resources first and then copy Pods resources (overwriting the resources you had in your main application).
You could change the order of "Copy Pods Resources" to an earlier phase by dragging it to above "Copy Bundle Resources".
You also have to verify that the image resource included in your main project, has a correct target membership, by clicking on the image resource -> file inspector -> target membership. It should be checked for the target you are compiling.
Upvotes: 0