Xcode: Which files need to be members of my target? (Target Membership) - ios

I'm developing an iPhone app in Xcode 4.6.2 that only has one target, and I've noticed that some important files are not members of my target. None of my custom header files are part of the target membership, nor is my Info.plist, my Prefix header, or the product "MyApp.app."
The way I understand targets, these files certainly need to be members of the target.
My question is: why aren't these files members of my target?
After searching around on SO, similar questions have yielded some insight, but not a complete answer to that question. The insight I've gathered is:
Header files are not members of your target because they get linked in the "Copy Headers" Build Phase.
This sounds reasonable, but I don't have a Copy Headers Build Phase
Info.plist and Prefix.pch aren't members of the target because Info.plist gets linked in the "Copy Bundle Resources" Build Phase, and the Info.plist contains a key/value entry that points to the prefix header (Prefix.pch)
I'm not positive that this is actually how it works

Header files are what other source files reference so that they know what the interface for a class is. They aren't needed as part of the binary itself, so they don't need to be included in the final product.
Info.plist is a special case as it defines the application bundle itself, so it is processed separately.
Generally speaking, you want files to be members of your target when they:
Form part of the executable (e.g. implementation (.m) files or libraries), or
Are included as files in the application bundle (e.g. images).
You don't need files to be members of your target if they are only used as part of the build process and aren't needed at runtime. Typically this is any type of header file, including precompiled headers (.pch).

Only .m files and resource files are part of the targets, not .h.
You are right: the Info.plist files and the headers are all referenced in the build settings (which again are target specific).

Headers only need to be copied for a framework target, and only because they are part of the framework release (they allow users to know how to use the framework). Apps don't need the headers because they're compiled stand alone entities. The headers (and the pch file) are used during compilation but aren't required at runtime.
The info.plist is handled differently. It usually can't just be copied because in the project it usually isn't called "Info.plist". It's also mandatory for the file to exist in the app so Xcode doesn't give you the option of not including it.

Related

Add Files and Select Multiple Targets in Xcode

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).

Use an entire app as a dependency?

Without going into the why, I need to use an entire app for various classes and libraries it has and includes.
Is there a way I can use the entire project as a dependency? When I choose "static library target" I lose all the hundreds of classes in the "compile" step. Effectively I would like to be able to package the project such that I can use it elsewhere.
Is there an easy way to do this aside from building my new app out of the old app and changing the app name/launch targets?
You have to find a way to transport every element into the new XCode project. iOS app consists of:
main.m file - You probably won't need to copy that, as it's usually just one line.
Source files and headers for: appDelegate, ViewControllers etc. - I don't understand why you would "lose all the hundreds of classes" during compile time. You're the one that chooses what is to be included in the static library. Add all the header files you need to "Copy headers" in the static library target "Build Phases". Add all the source files into "Compile sources". There are many tutorials and StackOverflow posts on how to do that. (example: How can I create static library and can add just .a file on any project in ios)
Storyboards, xib files, *.plist files, images and other resources - you need to put these in a *.bundle file . Just create a new target (which is a bundle) and include all the needed resources in it. Then you'll have to find a way to use them in the new XCode project. For example setting the default *-info.plist or *.pch file: How to tell Xcode where my info.plist and .pch files are or setting the main storyboard.
So you end up with two files: one framework/static library and one bundle file. It shouldn't be that hard to configure new XCode project to use resources from the bundle and classes from the static library.
I'm not sure if I understood your question.
You can add your old app as a project to your workspace and add it as a "target dependency" to use it.
The easiest and safest way to do this is to copy the whole workspace and change the initial view controller.

Assets using targets with Xcode

I'm working with an iOS app with mĂșltiple targets and at this moment, I have a critical doubt.
The project has two targets, target A and B, and each target has different set of images.
My question is:
If I upload the target A to iTunes Connect, this target will contain also the images of the target B, or this target (A) only will contain her images?
Target A and Target B would have the same images only if you set it up as such. Each target can have its own set of source files and assets. If you look select items (whether it be source files, frameworks, or other asset files) and have the File Inspector on, you'll see something called Target Membership. This indicates which target it belongs to.
When you Add File(s), there is also a dialog that indicates which targets to add it to.
The Build Phase of the target will also show you the files that are compiled as well as files that are copied into the binary and the libraries used to link.
Note there are multiple ways to add/remove files from the target.

Integrating .a library file types with XCode

I am testing an image capture library that sent over their code library as a regular header file and a file ending in a "*.a" extension. I am not familiar with using a file in this format and can't seem to find the right "magic" to search for.
What does this file extension stand for?
What if any extra steps are needed to get it integrated with my XCode project?
Maybe a bit more of theory can get you in the right track so you'll know how to search next time:
.a files are archives of object (.o) files. These object files are generally produced by an assembler, compiler, or other language translator; They contain machine code that is usually not directly executable, but are used by linker tools to generate an executable or yet another library by combining parts of these object files.
Another important thing you should know is that since these files contain machine code, they must have been compiled for the correct architecture you're targeting for (ex.: armv7, i386, etc). That can be the reason why sometimes you will be able build your project for one device but not to another if you don't have the right set of files for the targeted platform (e.g. iPhone simulator vs. actual iPhone).
It is also possible to have "universal binaries", which are files that in turn package together archives of object files (.a) for different architectures (e.g. using tools such as lipo), so that the same library file can be given to the linker for multiple architectures. Or, you may have a different linker configuration for each target (e.g. using conditional build settings in XCode). All of these files can be analyzed with certain tools (e.g. "file", "otool", "lipo -info", etc), and each has several parameters to play with. Debuggers will also check the symbols within these files for their own purposes.
When you drag the '.a' file to your project's directory within Xcode, you can notice that it will automatically add this file to the list of "Link Binary With Libraries" items under your target's "Build Phases".
Since the header files allows us to separate certain elements of a program's source code into reusable files, that commonly contain forward declarations of classes, subroutines, variables, and other identifiers that are needed for reference during the compilation step, it is common to have libraries provided as archives of compiled objects (.o) in ".a" files along with their respective headers. For instance, as soon as you include the headers files in your XCode project, the editor will provide auto-complete for these new functions.
Sometimes, you might also consider having the actual source code of the library instead of binaries inside your project as this * might * make debugging easier in case an unexpected behavior is happening inside that "library" package. Many times this is not an option though (when you have no access to the sources) when the binary distribution is made in purpose to hide implementation details (commercial libraries).
.a stands for archive. It is also known as a static library. I believe you should be able just to drag it and the header files into Xcode. Xcode should pick up the right thing to do from its extension.
Example, see appr. from 30 sec here
http://memention.com/ac3dreader/usage/quickstart.html
Another example from Google Analytics, under Setup
Drag GANTracker.h and libGoogleAnalytics.a from the SDK's Library directory into your new project.
https://developers.google.com/analytics/devguides/collection/ios/devguide

What's the best way to swap Xcode contents for projects intended for many clients?

I've got a relatively large Xcode project that produces a single app. However, I have many clients/customers who require deep customization and branding of said app. These configurations include different graphics, a few different interfaces and implementations, and, perhaps most importantly, .xcconfig files.
My Xcode project has a dedicated group that points to a particular client's customization folder on disk, so by opening the Xcode project and building, you get a build of the single app with the current client's customizations. To switch to another client, I change where that group points to on disk. (I also change and switch-back the xcconfig "Based On" settings in the project's Info pane to reload the full xcconfig inheritance; Simply changing the group containing one or more xcconfig files doesn't reload this!) This has worked great for 100+ clients. It's a little tedious to switch this folder every time you need to build the app for a different client and ensure the xcconfig is correct, but it works.
Now I'm in the process of automating builds via the command line, and running into troubles. The quick and dirty solution to pointing the aforementioned Xcode group at a different customization folder was to copy the ProjectName.xcodeproj/project.pbxproj file to ProjectName.xcodeproj/project-template.pbxproj and put placeholders inside this file that can be grepped and replaced with the name and path of the desired customization folder. Then, temporarily overwrite project.pbxproj with the modified project-template.pbxproj, and build to get the correct app.
As you've probably observed, the project.pbxproj was duplicated and modified, and will therefore get out of sync as developers modify the original and forget to also update the template. And besides, I shouldn't really be messing with pbxproj files in this fashion anyway -- that's Xcode's private stuff.
So, is there a better way to tell Xcode about a folder full of resources, code, and config files perhaps during the Build Phase with a script or environment variable, rather than at the project group level? The most complicated bit seems to be the xcconfig chain, since each client has their own xcconfig file that inherits from the single app's Debug, Development, and Distribution xcconfig files.
Sorry for the long-windedness of this question, but it's a little complicated! Any suggestions would be greatly appreciated!
I think you would way better off using the targets feature in Xcode. Have one project and the resources of every clients in that project.
You can then duplicate the target you already have (right-click on your target, by selecting the project file in Xcode's Project Navigator).
All your targets will be compiled with the same code. You just need to change the resources in Build Phases > Copy Bundle Resources to have different app created for each target. No need to look at Xcode's internal files.
You can even change the code in your source files by adding a preprocessor macro in your build options (something like FIRST_CLIENT=1) and then look for these definition in your file with #if FIRST_CLIENT.
I have a project set-up like this and it works pretty well :

Resources