{"id":1343,"date":"2015-04-17T07:12:22","date_gmt":"2015-04-17T13:12:22","guid":{"rendered":"http:\/\/dev.iachieved.it\/iachievedit\/?p=1343"},"modified":"2019-12-22T10:59:23","modified_gmt":"2019-12-22T16:59:23","slug":"multiple-build-schemes-with-apple-watch","status":"publish","type":"post","link":"https:\/\/dev.iachieved.it\/iachievedit\/multiple-build-schemes-with-apple-watch\/","title":{"rendered":"Multiple Build Schemes with Apple Watch"},"content":{"rendered":"<p>I frequently use Xcode <i>schemes<\/i> and <i>configurations<\/i> to manage building iPhone applications for specific environments.  For example, let&#8217;s say you&#8217;re integrating with an API from another team, and they&#8217;ve set up two instances of the API:  <i>staging<\/i> and <i>production<\/i>.  Furthermore, you want to have two sets of builds for those environments:  <i>debug<\/i> and <i>release<\/i>.  All of this can be accomplished with Xcode and Swift, with details outlined in a  <a href=\"http:\/\/dev.iachieved.it\/iachievedit\/build-configuration-management-with-swift\/\">previous blog post<\/a>.<\/p>\n<p>In this post I&#8217;ll show you how to extend this paradigm to work with an Apple Watch target that you&#8217;ve added to your project.  We&#8217;ll start with an application that is already configured to support two schemes:  debug and release, where the debug scheme enables logging.  Download the starter project <a href=\"https:\/\/joeiachievedit@bitbucket.org\/joeiachievedit\/watchschemes\/get\/master.zip\"><b>watchschemes<\/b><\/a>.  To ensure things are working properly, download the zip file and open the <b>watchschemes.xcodeproj<\/b> project, and then run the <b>Debug Application<\/b> scheme.  You should get a nice log in the console:<\/p>\n<pre>\n2015-04-16 21:47:30.056 [Info] : watchschemes Version: 1.0 Build: 1 PID: 51960\n2015-04-16 21:47:30.056 [Info] : XCGLogger Version: 1.8.1 - LogLevel: Debug\n2015-04-16 21:47:30.059 [Debug] [AppDelegate.swift:27] application(_:didFinishLaunchingWithOptions:): ENTRY\n<\/pre>\n<p>Before we add the Apple Watch target, note our two files that facilitate logging:  <code>XCGLogger.swift<\/code> and <code>LogUtils.swift<\/code>.  They are currently grouped under <code>Supporting Files<\/code> of our <code>watchschemes<\/code> folder.  When we add the Apple Watch target we&#8217;ll reorganize these files to highlight the fact that they are shared between the iPhone application and watch extension.  If you haven&#8217;t had the pleasure of working with XCGLogger, see our <a href=\"https:\/\/dev.iachieved.it\/iachievedit\/swift-logging-with-xcglogger\/\">post on using XCGLogger instead of Lumberjack<\/a> for your Swift projects.<\/p>\n<p>Now, let&#8217;s add our Watch target.  Go to Xcode <b>File &#8211; New &#8211; Target<\/b> and select the Apple Watch &#8220;WatchKit App&#8221; template.  Uncheck <b>Include Notification Scene<\/b> as we won&#8217;t be creating one.<\/p>\n<p><a href=\"https:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2015\/04\/watchkitapptarget.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2015\/04\/watchkitapptarget.png\" alt=\"watchkitapptarget\" width=\"413\" height=\"185\" class=\"alignnone size-full wp-image-1354\" \/><\/a><\/p>\n<p>You will notice that Xcode has created a new <b>scheme<\/b> titled <b>watcheschemes WatchKit App<\/b>.  Xcode may ask if you want to activate that new scheme:<\/p>\n<p><a href=\"https:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2015\/04\/activatescheme.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2015\/04\/activatescheme.png\" alt=\"activatescheme\" width=\"425\" height=\"218\" class=\"alignnone size-full wp-image-1382\" \/><\/a><\/p>\n<p>Click <b>Activate<\/b>.<\/p>\n<p>You will also notice if you edit the scheme you will find that the <b>Run<\/b> action is associated with the <b>Debug<\/b> build configuration.<\/p>\n<p><a href=\"https:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2015\/04\/watchkitscheme.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2015\/04\/watchkitscheme.png\" alt=\"watchkitscheme\" width=\"724\" height=\"316\" class=\"alignnone size-full wp-image-1368\" \/><\/a><\/p>\n<p>What we would like is to have two schemes for our WatchKit App, similar to the two schemes we have for the iPhone application.  Let&#8217;s do that then by going to the <b>Manage Schemes<\/b> page.  To get there, select the Scheme in Xcode and go down to <b>Manage Schemes<\/b>.<\/p>\n<p><a href=\"https:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2015\/04\/manageschemes_selection.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2015\/04\/manageschemes_selection.png\" alt=\"manageschemes_selection\" width=\"439\" height=\"157\" class=\"alignnone size-full wp-image-1355\" \/><\/a><\/p>\n<p>You should see the three schemes in the project:<\/p>\n<p><a href=\"https:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2015\/04\/schemelist.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2015\/04\/schemelist.png\" alt=\"schemelist\" width=\"771\" height=\"435\" class=\"alignnone size-full wp-image-1356\" \/><\/a><\/p>\n<p>The first thing we&#8217;ll do is rename the default WatchKit application scheme to <b>Debug WatchKit Application<\/b> and mark it as a shared scheme (sharing the scheme allows for multiple developers to share the scheme in their workflow, allow them to use all of the build configuration defines, optimizations, etc.).  Then, we will duplicate that scheme and rename it to <b>Release WatchKit Application<\/b>.<\/p>\n<p><a href=\"https:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2015\/04\/duplicatescheme.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2015\/04\/duplicatescheme.png\" alt=\"duplicatescheme\" width=\"773\" height=\"439\" class=\"alignnone size-full wp-image-1357\" \/><\/a><\/p>\n<p>When duplicating the scheme, rename it to <b>Release WatchKit Application<\/b> and change the build configuration for the <b>Run<\/b> action from <b>Debug<\/b> to <\/b>Release<\/b>.  After duplicating the scheme mark the scheme as <b>Shared<\/b>.<\/p>\n<p>Now that we have a Debug and Release WatchKit Application, let&#8217;s instrument logging into the WatchKit extension such that Debug has meaning.  Open the <code>InterfaceController.swift<\/code> file (in the extension group) and ensure it looks like this:<\/p>\n<pre class=\"lang:swift decode:true\">\nimport WatchKit\nimport Foundation\n\nlet log = XCGLogger.defaultInstance()\n\nclass InterfaceController: WKInterfaceController {\n  \n  override func awakeWithContext(context: AnyObject?) {\n    super.awakeWithContext(context)\n    \n    #if Debug\n      log.setup(logLevel: .Debug, showLogLevel: true, showFileNames: true, showLineNumbers: true, writeToFile: nil)\n      #else\n      log.setup(logLevel: .Severe, showLogLevel: true, showFileNames: true, showLineNumbers: true, writeToFile: nil)\n    #endif\n    \n    ENTRY_LOG()\n\n    EXIT_LOG()\n  }\n  \n  override func willActivate() {\n    ENTRY_LOG()\n    super.willActivate()\n    EXIT_LOG()\n  }\n  \n  override func didDeactivate() {\n    ENTRY_LOG()\n    super.didDeactivate()\n    EXIT_LOG()\n  }\n  \n}\n<\/pre>\n<p>Out of the box, with no changes to the extension target, this code will not compile.  The WatchKit extension has no knowledge of the <code>XCGLogger.swift<\/code> and <code>LogUtils.swift<\/code> code that is a part of the iOS application.  So let&#8217;s add them.<\/p>\n<p><b>Tip:<\/b>  If you interested in how the <code>ENTRY_LOG()<\/code> and <code>EXIT_LOG()<\/code> routines work, see the <code>LogUtils.swift<\/code> file.<\/p>\n<p>Go to the <b>watchschemes WatchKit Extension<\/b> target&#8217;s <b>Build Phases<\/b> pane and under the <b>Compile Sources<\/b> section add both <code>XCGLogger.swift<\/code> and <code>LogUtils.swift<\/code>.  This simply instructs Xcode to consult these files when compiling the WatchKit extension.<\/p>\n<p>Before adding the two Swift files you should see only the <code>InterfaceController.swift<\/code> file as a member of the <b>Compile Sources<\/b> list:<\/p>\n<p><a href=\"https:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2015\/04\/watchschemes_compile_sources_default.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2015\/04\/watchschemes_compile_sources_default.png\" alt=\"watchschemes_compile_sources_default\" width=\"814\" height=\"358\" class=\"alignnone size-full wp-image-1358\" \/><\/a><\/p>\n<p>After adding you should have 3 files:<\/p>\n<p><a href=\"https:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2015\/04\/watchkitextension_w_compile_sources.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2015\/04\/watchkitextension_w_compile_sources.png\" alt=\"watchkitextension_w_compile_sources\" width=\"791\" height=\"147\" class=\"alignnone size-full wp-image-1359\" \/><\/a><\/p>\n<p>Although we&#8217;ve added our logging files to the extension target, and we&#8217;ve specified the Debug and Release build configuration for the two schemes, one still must configure the build configurations for the extension target.  To put another way:  Xcode does <i>not<\/i> copy the build configuration flags and settings from the iOS target to the extension target when it is created.  You can verify this by looking at the <b>Swift Compiler &#8211; Custom Flags<\/b> for the WatchKit extension.  Whereas our original application has <code>-DDebug<\/code> set for the <b>Debug<\/b> build configuration, the extension target <i>does not<\/i>.  You should keep this in mind when creating your first Apple Watch target:  if you have compile-time flags configured for your iOS build configurations, you&#8217;ll need to reproduce them in your extension target flags.  This is what we have done here:<\/p>\n<p><a href=\"https:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2015\/04\/watchkit_custom_flags.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2015\/04\/watchkit_custom_flags.png\" alt=\"watchkit_custom_flags\" width=\"607\" height=\"131\" class=\"alignnone size-full wp-image-1360\" \/><\/a><\/p>\n<p>Once your build configuration flags have have been set you should be able to <b>Run<\/b> either the Debug or Release WatchKit Application.  For instant gratification, select the <b>Debug Watchkit Application<\/b> scheme and run.  You <i>should<\/i> see<\/p>\n<pre>\n2015-04-16 21:19:49.364 [Info] : watchschemes WatchKit Extension Version: 1.0 Build: 1.0 PID: 51664\n2015-04-16 21:19:49.364 [Info] : XCGLogger Version: 1.8.1 - LogLevel: Debug\n2015-04-16 21:19:49.372 [Debug] [InterfaceController.swift:24] awakeWithContext: ENTRY\n2015-04-16 21:19:49.373 [Debug] [InterfaceController.swift:26] awakeWithContext: EXIT\n2015-04-16 21:19:49.374 [Debug] [InterfaceController.swift:30] willActivate(): ENTRY\n2015-04-16 21:19:49.374 [Debug] [InterfaceController.swift:32] willActivate(): EXIT\n<\/pre>\n<p>in the console log for the <b>Debug WatchKit Application<\/b> scheme.<\/p>\n<p>As you continue development of your WatchKit application you can use the debug configuration.  Once you are ready to run the release version with no logging, switch over to the <b>Release WatchKit Application<\/b> scheme you created.<\/p>\n<p><b>Tip:<\/b>  With the two build configurations and schemes you can build either a WatchKit application that includes debug logging, or one that doesn&#8217;t.  I personally prefer to have additional configurations and schemes for targeting various installations of APIs or other backend services; the approach outlined above can be extended to accomplish this so you can support variations such as <b>Debug Staging<\/b> or <b>Release Beta<\/b>.<\/p>\n<p><b>Tip:<\/b>  Don&#8217;t forget your <b>Archive<\/b> scheme actions!  I frequently upload archive builds to either TestFlight or <a href=\"http:\/\/testfairy.com\/\">TestFairy<\/a> that have logging instrumentation, test API keys, or are utilizing staging servers.  You will want to ensure the <b>Archive<\/b> action for your scheme has the correct build configuration set.<\/p>\n<h3>Organizing Common Swift Files<\/h3>\n<p>As mentioned above, our <code>XCGLogger.swift<\/code> and <code>LogUtils.swift<\/code> files are utilized by both the iOS application and WatchKit extension.  To facilitate making this explicitly obvious in the project, I&#8217;ve started to add a <code>Common Sources<\/code> group to my Xcode projects and placing the shared files there.  In this project this looks like:<\/p>\n<p><a href=\"https:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2015\/04\/commonsources.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2015\/04\/commonsources.png\" alt=\"commonsources\" width=\"261\" height=\"239\" class=\"alignnone size-full wp-image-1364\" \/><\/a><\/p>\n<h3>Getting the Code<\/h3>\n<p>The final version of the code for this tutorial is on the <b>watchschemes<\/b> branch of the <a href=\"https:\/\/bitbucket.org\/joeiachievedit\/watchschemes\">BitBucket repository<\/a>.  To download a copy, grab <a href=\"https:\/\/joeiachievedit@bitbucket.org\/joeiachievedit\/watchschemes\/get\/watchschemes.zip\">this zip<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I frequently use Xcode schemes and configurations to manage building iPhone applications for specific environments. For example, let&#8217;s say you&#8217;re integrating with an API from another team, and they&#8217;ve set up two instances of the API: staging and production. Furthermore, you want to have two sets of builds for those environments: debug and release. All [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[11,16,2],"tags":[],"class_list":["post-1343","post","type-post","status-publish","format-standard","hentry","category-apple","category-apple-watch","category-xcodetips"],"_links":{"self":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts\/1343"}],"collection":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/comments?post=1343"}],"version-history":[{"count":33,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts\/1343\/revisions"}],"predecessor-version":[{"id":3933,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts\/1343\/revisions\/3933"}],"wp:attachment":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/media?parent=1343"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/categories?post=1343"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/tags?post=1343"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}