I have over 100 projects in my XCode and when I add a new file or class I have to select each target one by one to add it to it. Is there a way to select multiple targets instead?
The usual way is to have targets that don't duplicate each others files. E.g. some targets are libraries that are used by some others, and eventually there's an app or a unit test target that uses them. In this case there's no need to have the same file in multiple targets.
So consider refactoring the common files to a common library target that you can reference from the other targets. In this case when you add a file, you can add it to just that library, and it will be automatically resolved (linked) in the other targets.
Note also that in this case the file you add is only compiled once, and the compilation result is reused in various dependant targets, as opposed to compiling a separate version of that file for each target.
If that's not an option for you, an alternative is to generate the Xcode project file using some tool like CMake, GN, or a custom script that can write xcodeproj files (there are libraries to do that in various languages).
Related
I'm working on an xcode app using swift and xcode 8.1.
I keep adding files such as pictures and .plist files to my main folder with my storyboard, but each time it asks what targets I want to add it to. Should I be adding it to my test targets as well? If so, why? Whats the rule to know what targets to add it to.
No, you shouldn't add your files to the test target. Unit test target has access to your application files anyway.
According to the Apple documentation, target is a single build artifact. Because of that, you should only add the files which are building blocks of a specific target.
A target specifies a product to build and contains the instructions for building the product from a set of files in a project or workspace. A target defines a single product; it organizes the inputs into the build system—the source files and instructions for processing those source files—required to build that product. Projects can contain one or more targets, each of which produces one product.
For the most basic scenario with one application target and two test targets the general rule is as follows
Add application classes to the application target.
Add unit test case classes to the unit tests target.
Add UI test classes to the ui tests target.
In more complex scenarios you can have more targets in your application. You can have iMessage extension, share extension etc. You can also have multiple targets for building variants of the same applications but the general rule stays the same.
I'm trying to split my large Swift framework to many module frameworks so every module in my application will be independent in order to reuse on another apps.
Due to the fact that I have a big data like classes and libraries that shared with all of the modules I thought to create a core_framework contains share data and enforce the app to use this framework in order to enable use all the other frameworks (one or more)
I saw an example of FBSDK there is a core framework and other functionality frameworks : FBSDKCoreKit and FBSDKLoginKit
This is important to me that all the other frameworks will not contains the core framework for reasons of efficiency.
My question is - after creating the core framework what I have to do in my nodule framework so it's will recognize the core classes and functionality but will compile with out the core's files?
Thanks
When you split up a project into submodules, what you have to do is quite simple, though some details depend on how you partition your project.
Easiest case: 1 project with N targets
Say you only work on this one app and split it into modules. The easiest way is to add more Framework Targets to the project.
You then need to embed them in your app target. Make sure it's part of both "Embedded Binaries" and "Linked Frameworks and Libraries".
Now you have a new framework module.
Create a couple of them ("Core" and "Module 1", for example). Then:
In "Module 1"'s General project settings, add "Core" to "Linked Frameworks and Libraries". There's no embed option for frameworks, as they cannot include libraries, only the dependency on them.
In the app target, embed & link "Module 1".
That's all you need to set up.
I tried to diagram the embed and link settings so you see that only the app target contains the other frameworks:
Slightly more complex: multiple projects
The basic setup from above applies to all other variants: frameworks (modules) can depend on other frameworks, but they cannot ship with them. Only the application can finally resolve the binary file dependency.
If you split your project into multiple sub-projects, e.g. extracting deployable open source libraries for other people, then you have to make "Module 1" aware of "Core" in each project, linking to the "Core" module the same way as detailed above. What makes isolated Xcode projects a bit more complicated is: how does the "Module 1" project know about the Core.framework?
You could expose each module via Carthage and depend on one from the other,
you could use CocoaPods,
you could check out dependencies via git submodule.
The options above keep each module project autonomous. Dependencies are part of the directory tree of a module.
A bit less orderly:
You could create a Xcode workspace, drag all projects inside, then drag the Core.framework from the "Products" group of one project to the "Linked Libraries" list on another, or
drag the Core.framework file from the Finder onto the "Module 1" project (optionally selecting "Copy files if necessary" to put the resulting binary into the "Module 1" directory tree).
The above options can work, too, but they form assumptions about the location of files in the file system. The workspace approach should help to reduce problems with outdated framework binary files, though, as the workspace can help create formalize build dependencies from inter-project dependencies. Just like the app target depends on its framework targets, and like test targets depend on the app target to be compiled first.
To link binaries to you framework you can from build phase add your needed libraries to your project .. but what if I need to make some thing specific for example I need to customise my framework by adding or deleting binaries.. foe example I want lite version and full version so I need always to delete and add these binaries from "Link binary.." tab
Is there any dynamic way like to make different configuration files or some thing?
You'd need to create 2 Xcode targets, one for lite and one for pro, which compile the same source files and link to mostly the same frameworks etc.
You can also add compiler constants to the Build Settings of these targets, which will allow the common source files to behave differently between these target "products".
I have 3 applications that share a lot of functionality. It is only the content and styling changes between them.
Instead of simply duplicating the project for each app, is there a way to make a "base" application and then have the 3 applications extend this?
Simply duplicating the project would be horrible to maintain, whereas extending a "base" would allow them to all update simultaneously.
I know you could create the project and then copy all files from the old project into the new. This would keep the files up-to-date, however if any files were added or removed, you would have to manually do that.
Have one base project that uses multiple targets. Each target can include a subset of the files in your main project, and/or add their own independent files. Each target can also have its own set of preprocessor defines set up in the build configuration.
You can add more targets to your project in Xcode.
Create a project that builds a static library for the reusable components. You can use an Aggregate target to package any associated resources, such as nib files, storyboards, images, etc.
Your app projects can all then consume the static library and resources. Any changes to the static library will be available to all the dependent projects.
I'm including a 3rd party library (sources) with my static library. It it intended for device only (since it includes some ARM assembly routines) and I do not wish to build it for the simulator (I just want my app to compile there so I can test the GUI).
Creating another target for simulator only is not an option since my projects reference my library as a dependency and it would be a nightmare to maintain.
Adding #if (TARGET_OS_IPHONE) for those files is not an option as well since these are not my original sources and I would like to update them easily for updates (there are more than 200 files there and I do not with to modify all of them)
I'm looking for a way (similar to #if (TARGET_OS_IPHONE) in source files) which will work from the IDE itself (so I can exclude a file from the actual build process based on my target architecture). The only thing I found is an option to exclude/include a file from a target - but not for a specific architecture.
Is there a way to set architecture conditions per specific files?
Your best bet would be to separate the third party library into a new target that builds it as a static framework. Set it as a dependency for your project, and then set the static framework to be conditionally linked as described by Apple here: http://developer.apple.com/library/ios/documentation/Xcode/Conceptual/ios_development_workflow/115-Configuring_Applications/configuring_applications.html#//apple_ref/doc/uid/TP40007959-CH19-SW7
You can add a new target by selecting the Project in the project navigator and then hitting the Add Target button at the bottom of the Editor pane. You can setup a cocoa touch static library and then assign the relevant .m or .c files to belong only to that target. Then select your app's target and add the static framework in the "Target Dependencies" section of the Build Phases tab.
You can conditionally include/exclude files in Xcode using EXCLUDED_SOURCE_FILE_NAMES based on sdk. For example:
EXCLUDED_SOURCE_FILE_NAMES[sdk=*simulator*] = something.cpp something_else.cpp
See Conditional Compilation article for more details