In Xcode, what exactly is a scheme? - ios

At first I thought a scheme was a list of values for each build type. By default, there are two schemes, Debug and Release. In the app target, you customize each scheme on the fly by choosing the values (in the default case for either Debug or Release).
However, now I think the schemes are bigger than that. Your project comes with one scheme by default, and included in that scheme is the ability to customize settings for different build types, including run, test profile, etc... So in ONE scheme you can have settings xyz for the run phase, and in ANOTHER shceme you can have settings abc for the run phase.
I'm a little confused here. Can anyone simplify this?
Thanks

From Xcode's Help:
scheme
A scheme is a collection of settings that specify the targets to build for a project, the build configuration to use, and the executable environment to use when the product is launched. When you open an existing project (or create a new one), Xcode automatically creates a scheme for each target. The default scheme is named after your project.
Here, "build configuration" is what you're calling "Debug" and "Release" above.

Related

Adding dummy objects to project

I want to add dummy objects for testing in project, but I don't want them to be included in my final build. So I have my AppDelegate class and there in imports:
#ifdef TESTING
#import "DummyBeaconLocationManager.h"
#else
#import "BeaconLocationManager.h"
#endif
And later:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
...
#ifdef TESTING
[[DummyBeaconLocationManager sharedInstance] startRanging];
#else
self.beaconLocationManager = [BeaconLocationManager sharedInstance];
[self.beaconLocationManager startRanging];
#endif
return YES;
}
But the problem is that I have to include this in my Target Membership, not my test target. Is there a way to not include these files in my main target, but only in the Test target?
Edit:
Whats need to do is test my app after launch. I want to test it on simulator but app using beacons. So I created dummy objects that represent beacons and simulate location manager. When the app starts with TESTING option it not start ranging beacon but put a dummy objects as a beacon instead.
Once you follow these steps, you will be able to add test classes with test functionality to your build. To run your app using the test functionality, you should select the Testing scheme that is configured below.
Xcode Project Configuration (using Xcode 7.0.1)
To allow conditional imports and functionality to be effective for testing, you will need the following ingredients:
Testing Configuration
Testing Target
Testing Scheme
Short Explanation of Schemes, Targets and Build Configurations
Schemes point to targets and configurations.
Targets can be configured with different build settings.
Configurations can be added, to branch out target build settings.
Here are the steps:
1. Duplicate a Configuration for testing
With the project file selected in the Project Navigator, follow these steps:
Select the project target
Select Info
Select + to add a configuration
Select Duplicate "Debug" Configuration
Rename the new configuration, and drag it to re-order
2. Duplicate a Target for testing
Now that you have a testing configuration, add a testing target. With the project file select in the project navigator, follow these steps:
Right-click or Option-click an existing target, and select Duplicate.
Tap on the new target to rename it, then drag it to reorder your targets.
3. Manage Schemes
Now that you have a testing target and configuration, you are ready to add a scheme that points to the new target and configuration.
Tap on the schemes (next to the stop button), and select Manage Schemes...
In the Schemes manager popup, if you have elected to autocreate schemes, the new scheme will already be listed. Otherwise, you can tap + in the popup to add a scheme. Each scheme can be shared, as shown here:
Tap on the new scheme to rename it, and drag it to reorder:
To edit the new scheme, ensure that it is selected, and tap Edit...
In the edit panel, select the Testing build configuration
Ensure that the scheme points to the Testing Target, by tapping on the Executable drop-down:
Ensure the scheme is pointing to the correct build configuration, for other actions, such as Automated Testing:
4. Configure the build settings for your targets
Now that you have your testing scheme set up to point to the Testing configuration, it will behave exactly like the Debug configuration, until you modify the build settings. Follow these steps, to change build settings for your Testing configuration:
For most build settings, there is an option for each configuration. When choosing which configuration to use in your settings, ensure the main target is selected:
The Preprocessor Macros are under the section titled 'Apple LLVM 7.0 - Preprocessing':
Tap on a row, to select it, tap the enter key to edit and commit your changes, use the arrow keys to move up or down. It is a good practice to define all your preprocessor macros for all configurations, like this:
5. Add a class to your Testing target
Now, the Testing Scheme points to a configuration that behaves differently from your Debug configuration. You should now be able to select the Testing scheme from the schemes dropdown menu, and run your Testing configuration.
You can modify the target membership of a class in one of two ways.
When you create a new file, the third panel where you can choose the location, has options at the bottom, for each target:
When you select a file in your Project Navigator, the File Inspector has a Target Membership panel where you can make modifications:
Schemes
Schemes are usually paired to build configurations. One good practice is to have a scheme/configuration for each audience that needs a different version of your build. Here are some basic audiences that typically need separate configurations:
Developer > DEBUG
Developer > TESTING
Internal Testing > DEVELOPMENT
Beta Testers / Production > APP STORE
Subclassing
If you want to modify any functionality in testing mode, you could use a subclass, and only add the subclass to your testing target.
Alright, if I got it right, you should:
a) Create a separate target for testing porposes (as #Carl Veazey and
#Rainer Schwarze suggest) with almost the same code base as your main
target.
b) I would recommend mocking your location manager and beacon
objects via subclassing from BeaconLocationManager and YourBeacon
(for example). Then, you just override the real behavior with your
simulator-specific actions.
At the end of the day, your testing target will only contain 2 more classes (mock beacon manager and mock beacon) comparing to the main target. No additional changes on the project structure or code semantics reuired. Good luck.
I could vary easily be wrong on this, but I am guessing this might work:
Like when using cocoapods, when you create the pod file you deselect the target (Project Name). What if you do that, then select the target (Project NameTests)

Make Target's Build Products Path in Xcode dependent on Current Scheme

I have an Xcode Project with three targets:
A Mac app to be distributed on the Mac App Store
The same Mac app, but to be distributed as a demo version on my
website
A login helper app that is a target dependency for the first two
targets
The login helper app is copied on build to the target of the current scheme (let's say the first target), which has a build path of
$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
When I change the scheme to the second target (the demo), I'd like for the build products path of the third target to be the same, except with _Demo attached to it. Basically, the third target's build path should always be the same as the current scheme's target (either target one or two).
Currently, I do it manually before building, but that's tedious.
Is there no way to make the Per-configuration Build Products Path (and the Per-configuration Intermediate Build Files Path, etc) dependent on the current target?
So when I select the first target, no _Demo gets attached to the path, when I select the second target, _Demo does get attached to the path.
Any pointers would be highly appreciated.
Thank you very much,
Matt
As I understand it, you want the login helper’s building to be aware of which “parent target” it’s being built in. Not sure if that’s possible.
What I’d do in this case, is add a separate “Copy” build step into targets 1 and 2. It sounds like copy is currently a part of building target 3, but it works better if it’s part of building targets 1 and 2.
I have a very similar situation with a command-line helper in one of my tools. Here’s the relevant part of my build settings.

Xcode: What is a target and scheme in plain language?

Yeah the title says it :-) What do they mean in plain English language? I really don't understand the explanation on Apple's website and I need to rename my target and I'm afraid that nothing works after that..
I've added in Workspace and Project too!
Workspace - Contains one or more projects. These projects usually relate to one another
Project - Contains code and resources, etc. (You'll be used to these!)
Target - Each project has one or more targets.
Each target defines a list of build settings for that project
Each target also defines a list of classes, resources, custom scripts etc to include/ use when building.
Targets are usually used for different distributions of the same project.
For example, my project has two targets, a "normal" build and an "office" build that has extra testing features and may contain several background music tracks and a button to change the track (as it currently does).
You'll be used to adding classes and resources to your default target as you add them.
You can pick and choose which classes / resources are added to which target.
In my example, I have a "DebugHandler" class that is added to my office build
If you add tests, this also adds a new target.
Scheme - A scheme defines what happens when you press "Build", "Test", "Profile", etc.
Usually, each target has at least one scheme
You can autocreate schemes for your targets by going to Scheme > Manage Schemes and pressing "Autocreate Schemes Now"
A target is an end product created by running "build" in Xcode. It might be an app, or a framework, or static library, or a unit test bundle. Whatever it is, it generally corresponds to a single item in the "built products" folder.
A scheme represents a collection of targets that you work with together. It defines which targets are used when you choose various actions in Xcode (Run, Test, Profile, etc.) Often, you will have just one scheme, which uses the main app target for the Run, Archive, and Profile actions, and a unit test target for the Test action. If you were building two related apps, you might have two schemes that used the same unit test bundle but different app targets.
The main benefit of schemes (introduced in Xcode 4) is that they allow you to switch between running your app and your unit tests without needing to toggle the selected target.
I am a visual person, hence to explain the concept I will be using a diagram.
When you have multiple targets they can be one-to-one matched with Xcode's Run,Test,Profile actions, this concept defines a scheme
A target is a version of your Project,i.e targets differ slightly in classes & resources to use during built time. A project can have multiple built time setting for separate distribution requirements.
Xcode structure
Workspace
-> Project
-> Target
-> Dependency
-> Scheme
-> Action
-> Build Configuration
-> Build Configuration File(.xcconfig)
Workspace (.xcworkspace) - is a container of multiple projects. It was created as a next step of cross-project references[About]
Workspace contains all schemes from included projects
Workspace handles all implicit dependencies[About]
Observations:
It is safe to work with different projects inside the same workspace and do not catch
//if you try to open two projects on two Xcode instances
Couldn't load Project.xcodeproj because it is already opened from another project or workspace
Cocoapods[About] working with workspace where creates Pods project
Project (.xcodeproj) - It is a container for targets and scheme. It defines code files, resources...
Also Projects manages Build Configuration(changed by scheme) and Build Configuration File[About]
You can convert existing Project into Workspace
File -> Save As Workspace...
[Workspace vs Project]
Target - PBXNativeTarget section. Defines a specific set of build settings that generate:
Application target
Library and framework targets
Test
Aggregate[About]. E.g. it is used to create a Universal framework or Umbrella framework
Scheme
Contains action(run, test, profile, analyze, archive) + configuration(additional arguments, [Build Configuration], diagnostic)
Scheme can be shared which helps you in CI, Carthage[Example]... and located:
<project_path>/<project_name>.xcodeproj/xcshareddata/xcschemes
Dependency - Targets can have dependencies. Dependency is a source link against. These dependencies can be linked statically or dynamically[About] There are two types of them:
Explicit Dependency[About] - Source code of the dependency that is located in the same project or nested project
Implicit Dependency[About] - Source/closed code of the dependency that is located in the project that is a part of the same workspace.
[Vocabulary]
tldr; Targets contain instructions to build a module/framework/library or an App/end Product e.g. instructions to build a watchOS app and an iOS App. Schemes know how to respond to certain actions e.g. a build action or test action or archive action.
Make sure you See WWDC16 video — Introduction to Xcode [45:13]. If you wanted to gain deeper knowledge then watch the entirety of the video. The video is simple to follow yet very foundational. My answer is mostly off of that.
Scheme
A scheme is how you specify what you want to run and it also contains
information about how you want to run it.
For example, I could have a project with an iOS app and a Watch app,
and in that case, I would have one scheme to run my iOS app and one
scheme to run my Watch app
Run will run my app in the debugger.
Test will run my tests.
Profile will run my app in instruments so I can measure its
performance.
Analyze will run Xcode's static analyzer and help catch problems I
might otherwise have missed.
And finally, the Archive action will build my app for release and put
it in the archive that I can then use to distribute to my testers or
to the App Store or to save for future crash log de-symbolication, or
symbolication.
Project
A project is a document that you use to organize your code an
resources in Xcode.
You have references to source code files and resource files on disc,
targets which actually build those files into products like your app,
Build settings which configure how your targets build their products,
and schemes which configure how you perform actions, such as Run, with
your targets.
Now, to access your project settings, you select your project in the
navigator, you select the popover at the top of the editor, and select
your project there.
Target
You have references to source code files and resource files on disc,
targets which actually build those files into products like your app,
Build settings which configure how your targets build their products,
and schemes which configure how you perform actions, such as Run [test, build], with
your targets.
A target contains the instructions to build one thing like an app or a
framework.
The thing that your target produces is called its product. The set of
steps that your target takes to build its product are called build
phases.
And lastly, a target has Build settings to configure how it builds its
product.
Now, one thing to note is that both projects and targets have Build
settings, and targets inherit the value set at the project level but
can override them with a target-specific value.
A target's build phases do things like cause dependencies to build
first, compile the source files in that target, and link the target
against libraries and frameworks.
To summarize:
Targets
Helps put a set of files together to build/run a product/module/package
Usually it ends up just being a product you ship to app store.
But often it can be a module that you just run unit-tests against it.
Like a single app can have an iOS target along with a watchOS target. Or just a single iOS Target. Or a single iOS target along with a test target, etc.
If you go to your target's Build Phase >> Compile Sources you'll see every file that's being built for that target. Example:
To explicitly quote Apple docs:
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.
The instructions for building a product take the form of build settings and build phases, which you can examine and edit in the Xcode project editor. A target inherits the project build settings, but you can override any of the project settings by specifying different settings at the target level. There can be only one active target at a time; the Xcode scheme specifies the active target.
A target and the product it creates can be related to another target. If a target requires the output of another target in order to build, the first target is said to depend upon the second. If both targets are in the same workspace, Xcode can discover the dependency, in which case it builds the products in the required order. Such a relationship is referred to as an implicit dependency. You can also specify explicit target dependencies in your build settings, and you can specify that two targets that Xcode might expect to have an implicit dependency are actually not dependent. For example, you might build both a library and an application that links against that library in the same workspace. Xcode can discover this relationship and automatically build the library first. However, if you actually want to link against a version of the library other than the one built in the workspace, you can create an explicit dependency in your build settings, which overrides this implicit dependency.
Schemes
A given target can be put through different actions.
build
run
test
profile
archive
You can have a scheme that has all the diagnostics enabled (which makes debugging slow) vs. a scheme that doesn't have any. Or a scheme that runs certain performance related tests vs. a scheme that runs both unit-tests and performance tests. You can edit a scheme so that it performs such actions as:
Building multiple targets
Executing scripts before or after any action
Sending emails before or after any action
Running with memory management diagnostics
Producing either a debug or release build for any action.
For more on that see Customizing the build schemes for a project
To put it all together:
Once you hit run, Xcode will look at the selected scheme. It will find its associated target(s). Use the Build Phases of that target and its Build Settings (any Project Settings that isn't overridden by the target settings will get included) to build a product into the selected destination (the destination can be an iPhone simulator or a physical iPhone or watchOS, etc).
AGAIN WATCH THE WWDC VIDEO!
My take:
Target -- a lower abstraction -- various kinds of builds. Each target has its own Build Settings (so if you split into several targets, take care of that huge sheet individually for each target). Targets have a convenient way of including/excluding files, so you can configure the build effectively on a per-file basis.
Scheme -- a higher abstraction -- guides a target through various ways of deployment (Run, Test, Archive). Has modest ways of configuring the build through Environment Parameters, but employs the Build Settings from the target. Creating / editing / deleting schemes is cheaper and easier than targets.
You can have several schemes guiding one target in several different ways.

How to find out if a build is debug or release

Is there a compile time variable that lets me detect whether the current build is for debug or release? If not, how can I define my own?
As of Xcode 4, the Build, Run, Test, and Analyze actions produce Debug builds by default; the Profile and Archive actions produce Release builds. This is controlled by editing the scheme, selecting the action, then changing the build configuration under the Info tab. To Apple in Xcode 4, the Archive action is the final "build this for release so I can distribute it" action. This is the highest level at which you manage these settings.
At the lower level, your target contains its build settings, which define configurations. By default, there are two configurations: Debug and Release. You can find (and manage) them by selecting the project (the root node) in the Project navigator, then choosing the Info tab. They're found under the Configurations group.
To edit the settings for the various configurations for a given target, choose the target in the Targets list, then choose the Build Settings tab. The grid looks (and sort of is) complicated and you should read the docs for details (esp. the what the different columns represent). To answer your question, each setting can be edited to change the setting for all configurations or expanded with the disclosure triangle so you can specify configuration-dependent settings. For example: under Release configuration, you might want to strip debugging symbols; under Debug, you do not.

Where is set the active build configuration in Xcode 4

I have 3 configurations in my project (Debug, Distribution_AdHoc and Distribution_AppStore). In Xcode 3 we had a list to choose device, version, configuration and target before build and run. Now with Xcode 4 we only have the device kind and version in this list. This bring my two questions:
So where is defined the configuration used ? Is that the configuration defined in "Project > Info > Command-line builds use: Debug" ?
And now the "Project" menu is replaced by "Product" So where can we create (or duplicate and edit) a Configuration ?
Thank you.
Just in case you still want to make a Distribution config (or other config--I still find them useful), after great length (read: searched in the help for 'duplicate'), I found this:
At first, they were all grayed out; this was because I had one of the targets highlighted in the editor (MFE, MFETests, etc.). If you highlight your project (as in the screenshot), they become enabled.
You can use alt(option) and click on either, run, test or profile to see the option.
Here you can set the target for each option.
For Archive the release is normally used, since can you resign your app via the organizer there is no need ad-hoc and appstore target any more.
For part 1 of your question,
The configuration is set in the schema window. apple+shift+comma to get to the window. Or Product > Scheme > Manage Schemes from the menu bar.
In the window, click the type of build you want on the left panel: Build, Run, Profile, Analyze, or Archive. In the window tab usually, along the type, there is an option Build Configuration that can be set. Select Debug, Release, or whichever configuration you want there.
The exception if the build task. The build task uses whatever configuration is set for the Run task. Also, the analyze and archive tasks only have one tab, so using the info tab is not necessity.
Apparently, "build" is shorthand for "build for run"...

Resources