Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
74 lines (39 sloc) 10.3 KB

How to Xcode

Xcode is the standard IDE for building apps for Apple's platforms (iOS, macOS, tvOS, watchOS). There are a lot of opinions regarding how good it is. There's a lot of terminology used throughout the whole Xcode and build process that can be opaque.


A Workspace is the highest-level organizational unit. It combines multiple projects together so they can reference code in each other easily. It is stored in an .xcworkspace folder. This is what you need to use if you use CocoaPods, because that creates a project for the pods to live alongside your actual project.

A Project is the high-level organizational unit. It defines the base settings used by targets. It also defines the build configuration files to be used for the defined build configurations. It is stored in an .xcodeproj folder.

A Build Configuration defines an abstract idea of the purpose of the build (e.g. development, test, production). In a project, each build configuration is associated with a .xcconfig file that defines a series of constants; these are things like flags for clang or constants that can be used in the code. They can include each other, so you can have common settings between configurations. You can also have separate build settings per build configuration. These configurations can help provide signing information for command-line builds.

A Build Setting is one of the flags in the Build Settings tab. These settings can be set at the project level (per build configuration) or at the target level (per build configuration). These flags do a myriad of things, such as compiler flags and code signing settings. If you look at the Levels setting, you can see the hierarchy of settings and how they are resolved for the selected project or target.

A Target defines a set of source files that are compiled and linked against each other. The target also defines frameworks to link agains, clang compilation options, and other configurable properties (such as entitlements and assets) to be used when doing that compilation. An info.plist file defines some of this basic information. Each (non-test) target defines one compiled product with (preferably) its own app identifier and bundle identifier.

A Test Target acts exactly like a normal target, except it is defined in terms of a Host Application, and allows the ability to run against the publicly exposed methods of that host. These are used for testing a target (hence the name). If you change the name or bundle ID of the Host Application, Xcode will claim the Test Target is pointing at the same place, but it's not; set its Host Application to None then back again to fix it.

A Scheme defines what the various actions in Xcode do. It provides definitions for Run, Build, Test, Profile, Analyze, and Archive. In the Build action, it defines the targets that get built for which of the remaining actions. The remaining actions define the preferred Build Configuration to use when building the targets (as defined in Build), along with some other configuration information. It is also possible with each action to define pre-run and post-run tasks. In general, there should be a scheme per build configuration per non-test target.


An Application Identifier or App ID is a reverse-DNS definition of an application. It defines a wildcard part of approved Bundle Identifiers for a Membership Program. You can also have an explicit App ID, which allows you to tie enabled services (such as Apple Pay or Push Notifications) to an application. Each App ID also needs to be associated with a team via its App ID Prefix, which is the 10-character Team ID.

A Merchant ID defines your ability to implement Apple Pay. Everything from the backend to the device has to use the same Merchant ID. Merchant IDs are tied to App IDs as an enabled service.

A Bundle Identifier is a reverse-DNS identifier of an application. It is a unique definition of an application, and is used to determine if e.g. a download is an update of an existing app on a device or a new app altogether. Only one instance of a bundle identifier can exist on a device at a time. In one target, you can set a different bundle identifier per build configuration (Target -> Build Settings -> Packaging -> Product Bundle Identifier). If you want a tvOS and iOS app to be linked, they need to have the same bundle identifier. For watchOS apps, they are tied to the iOS app and have .watchkitapp or .watchkitextension appended to the end.

A Product Name is the actual name of the application as it appears in Springboard and elsewhere in iOS. This can be overridden in the Info.plist file, by working through Xcode (Target -> Build Settings -> Packaging -> Product Name).

A Version Number is a public version in semantic version format for the public to see to identify the version of an app. A Build String is a private version in semantic version format for iTunes Connect to use to identify the version of an app. Both of these are used to correlate crash reports and .dSYM files. The expectation is that there may be multiple build strings per version number. Version numbers must be unique and continually increase globally; build strings must be unique within a version and increase within that version. People frequently have scripts to automatically update these values as appropriate.

A Deployment Target is the minimum version of iOS that can run the app, and provides a minimum level of functionality in the app. The Base SDK* is the actual SDK that the application is built against, and defines the upper limit of API calls. If the Deployment Target is less than the Base SDK, it is possible that @available annotations will need to be made in the code to handle the difference.


A Membership Program defines a collection of accounts that have permission to use Certificates, Identifiers, Devices, and Provisioning Profiles. The Membership Program is what costs money. There are two types of programs:

  • Base
  • Enterprise

A Team is the list of accounts attached to a membership program. Each team member can have different permissions on what they are able to do within the membership program, at a fidelity of three levels: Agent, Admin, and Member. There is one Agent, which is the account that manages the membership program.

An Account is just a run-of-the-mill Apple ID account. It must be added to a Membership Program to be useful. It also must be added to Xcode.

A Private Key is an RSA private key that exists in Keychain Access on a given development machine. There is an underlying assumption that there is one private key per machine and per developer. Private keys are kept in the keychain (use Keychain Access to view them); you want to make sure developer keys are in the login keychain, not the System keychain, or you will get weird build errors.

A Certificate is an RSA public key that is correlated with a private key in Keychain Access. Applications are signed with a particular certificate to verify that an application is not tampered with. Your certificate is known as your Signing Identity. Certificates can either be development certificates or distribution certificates, which are used by the different kinds of provisioning profiles. Certificates are kept in the keychain (use Keychain Access to view them); you want to make sure certificates are in the login keychain, not the System keychain, or you will get weird build errors.

An Entitlement is a specific capability or security permission that the app has. For example, enabling iCloud Storage, or Keychain Sharing. These must be specifically enabled, because information about the entitlement is used when signing the application; this provides a second check that an app has permission to do something it's trying to do, to try to prevent malicious actors.

A Device is an iOS device that has a UUID associated with it as its Device Identifier. A Membership Program has a set of devices associated with it.

A Provisioning Profile is a file that is placed on a device. It ties together an Application Identifier with a set of Device Identifiers with a set of Certificates. Once a Provisioning Profile is on a device (generally loaded via Xcode), it allows the identified application to be built and run on the identified devices by development machines that have one of the specified certificates. Each provisioning profile has a UUID.

There are multiple types of provisioning profiles, each existing for a different reason. A Development profile is used to sign the app locally to a machine; it is for debugging on device or simulator. On the other hand, a Distribution Profile is used to sign an app for distribution in some fashion. You cannot debug from Xcode on an app signed with a distribution profile. There are three kinds of distribution profiles:

  • An Ad-Hoc distribution profile requires a list of devices (maximum 100) that the app is signed against. Any developer account has access to this option.
  • An Enterprise (also called Universal) distribution profile does not require a list of devices that the app is signed against; therefore, the signed app can be distributed and run on any device. However, you need to have an enterprise membership program subscription to use this.
  • An App Store distribution profile is used to publish to the app store.

The Export Options declare how an app is going to be signed and configured. This is typically kept in an export_options.plist file.


An IPA is the actual installed application on a device. It is signed with a certificate that must be accepted on the device itself (?). It is a file with an extension of .ipa. You create this in Xcode by Product -> Archive or xcodebuild archive. The IPA provides a minimum and maximum version of iOS it can be run on, but it is otherwise built agnostic to the iOS version.

A Manifest File is a file of the name manifest.plist that is placed in the same directory as an IPA. It is automatically generated if you set up your export options correctly.

Useful Sources

[](Apple's Guide for Configuraing an Xcode Project)