{"id":256,"date":"2014-06-15T09:32:13","date_gmt":"2014-06-15T15:32:13","guid":{"rendered":"http:\/\/dev.iachieved.it\/iachievedit\/?p=256"},"modified":"2016-01-23T20:47:23","modified_gmt":"2016-01-24T02:47:23","slug":"logging-and-build-configurations-with-swift","status":"publish","type":"post","link":"https:\/\/dev.iachieved.it\/iachievedit\/logging-and-build-configurations-with-swift\/","title":{"rendered":"Logging and Build Configurations With Swift"},"content":{"rendered":"<p><b>Editor&#8217;s Note:<\/b>  This post came out shortly after the release of Swift in 2014.  It is not Swift 2.0-compliant, your mileage may vary!<\/p>\n<p>Well, that didn&#8217;t take long.  Mere days after Apple introduced Swift someone has <a href=\"https:\/\/github.com\/DaveWoodCom\/XCGLogger\">posted<\/a> what they ostensibly hope to be a replacement for Cocoa Lumberjack.  Not to be outdone, we&#8217;re introducing our Swift logging API, but a confessional:  ours is primitive and only useful if you typically use the Xcode console output for debugging.  The reality is that is what we do 99% of the time, so it should suffice for now.  <\/p>\n<p>You can download our file <code>Logging.swift<\/code> from <a href=\"https:\/\/github.com\/iachievedit\/swiftlog\">Github<\/a>.  We mean it, this is about as basic as it gets.  Variadic arguments to the log routines isn&#8217;t supported, i.e., use the Swift <code>\\(variable)<\/code> syntax to get at a variable&#8217;s value.  Don&#8217;t expect to be able to log a file (maybe we&#8217;ll get there).<\/p>\n<p>But, hey, this is pretty easy:<\/p>\n<pre class=\"lang:swift\">\r\nsLogLevel = .Verbose\r\n\r\nSLogVerbose(\"This will be printed only if the log level is SLogLevel.Verbose\")\r\n<\/pre>\n<p>The normal &#8220;logging rules&#8221; apply:  the lowest logging level is <code>.None<\/code>, that is, nothing will get logged.  The highest level is <code>.Verbose<\/code>, everything will get logged.  In between are <code>.Error<\/code>, <code>.Warning<\/code>, and <code>.Info<\/code>.  If the log level is set to, say, <code>.Warning<\/code>, both <code>SLogError()<\/code> and <code>SLogWarning()<\/code> will result in a log.<\/p>\n<p><b>An aside:<\/b>  We are using Swift&#8217;s new enumeration type and syntax in this post.  If you are unfamiliar with this syntax please see <a href=\"https:\/\/developer.apple.com\/library\/prerelease\/ios\/documentation\/swift\/conceptual\/swift_programming_language\/Enumerations.html\">Apple&#8217;s documentation<\/a>.<\/p>\n<p>Two convenience &#8220;macros&#8221; are also provided:  <code>ENTRY_LOG<\/code> and <code>EXIT_LOG<\/code>.  These are set to only emit a log at <code>.Verbose<\/code> level, and they include printing out the name of the function in which they were called.  The intent is to instrument your function calls as such:<\/p>\n<pre class=\"lang:swift\">\r\n  func multiply(a:Int, by b:Int) -> Int {\r\n    \r\n    ENTRY_LOG()\r\n    let r = a * b\r\n    SLogVerbose(\"\\(a) multiplied by \\(b) is \\(r)\")\r\n    EXIT_LOG()\r\n    \r\n    return r\r\n  }\r\n<\/pre>\n<pre class=\"crayon:false\">\r\n2014-06-14 18:29:45.574 buildconfigurations[3618:1291681] VERBOSE - ENTRY multiply(_:by:)\r\n2014-06-14 18:29:45.577 buildconfigurations[3618:1291681] VERBOSE - 6 multipled by 7 is 42\r\n2014-06-14 18:29:45.579 buildconfigurations[3618:1291681] VERBOSE - EXIT multiply(_:by:)multiply(_:by:)\r\n<\/pre>\n<p>Note that the <code>EXIT<\/code> log currently shows the signature of the function twice.  This is a known bug in XCode 6 Beta 1 (see <a href=\"http:\/\/openradar.appspot.com\/17219684\">here<\/a>).<\/p>\n<p>Our logging example is merely a means to end, however, which is demonstrating how to use build configurations for conditionally compiling in Swift code.  Unlike Objective-C, Swift does not have C-style macros and other preprocessor features.  Note that we said <i>C-style<\/i>, not that it didn&#8217;t have any of those features at all.  It does, they are just quite a bit different.  Apple puts it this way:  &#8220;<i>The Swift compiler does not include a preprocessor. Instead, it takes advantage of compile-time attributes, build configurations, and language features to accomplish the same functionality. For this reason, preprocessor directives are not imported in Swift.<\/i>&#8221;  So, whereas we used preprocessor macros and conditionals for all manner of &#8220;tricks&#8221;, in Swift we use other means to accomplish the same objectives.<\/p>\n<p>Our objective is to use build configurations to support multiple &#8220;types&#8221; of builds.  For example, we often need a build configured to communicate with a staging server, or a build configured with full debug logging.  You could even use this mechanism to create &#8220;branded&#8221; builds, i.e., the same functionality with different logos, color schemes, etc.  If you are unfamiliar with build configurations, see our post <a href=\"http:\/\/dev.iachieved.it\/iachievedit\/?p=37\">here<\/a>.<\/p>\n<p>In this example we are going have two build configurations:  <b>DebugStaging<\/b> and <b>ReleaseProduction<\/b>.  For debug builds we&#8217;ll set our logging level to <code>.Verbose<\/code>, and for our release builds we&#8217;ll set it to <code>.Error<\/code>.  For staging builds we want to use our staging webservices server at https:\/\/staging.webservice.net, and of course for production we&#8217;ll use the production services at https:\/\/production.webservice.net.<\/p>\n<p>To enforce the immutability of the webservice URL, we&#8217;ll create a Swift file called <code>Constants.swift<\/code> and add<\/p>\n<pre class=\"lang:swift\">\r\n#if Staging\r\n  let gWebServiceUrl = \"https:\/\/staging.webservice.net\"\r\n#endif\r\n\r\n#if Production\r\n  let gWebServiceUrl = \"https:\/\/production.webservice.net\"\r\n#endif\r\n<\/pre>\n<p>If neither <code>Staging<\/code> or <code>Production<\/code> is defined the project will not build as <code>gWebServiceUrl<\/code> will be unresolved.<\/p>\n<p>In our <code>application(_:didFinishLaunchingWithOptions:)<\/code> function we place<\/p>\n<pre class=\"lang:swift\">\r\n    #if Debug\r\n      slogLevel = SLogLevel.Verbose\r\n    #else\r\n      #if Release\r\n        slogLevel = SLogLevel.Error\r\n      #endif\r\n    #endif\r\n<\/pre>\n<p>This will set the logging level global flag (which defaults to <code>.None<\/code>) based upon whether we are building a debug or release build.<\/p>\n<p>Now, how to set the flags.  Easy.  In Xcode, click on your Project file in the Navigator pane (far-left).  The project file is the one with the blueprint icon.  Click the <b>Info<\/b> label first and create two new configurations for <b>DebugStaging<\/b> and <b>ReleaseProduction<\/b>.  To create a new build configuration, click on + under Configurations and select either <b>Debug<\/b> or <b>Release<\/b> (the two default build configurations created) and duplicate.  Then, you can rename by clicking on the name and changing the text.  Here&#8217;s what the Info pane should look like:<\/p>\n<p><a href=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2014\/06\/swift_build_configuration.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2014\/06\/swift_build_configuration.png\" alt=\"swift_build_configuration\" width=\"703\" height=\"255\" class=\"alignnone size-full wp-image-264\" \/><\/a><\/p>\n<p>Once that is complete go to the <b>Build Settings<\/b> pane and in the search box type <i>Swift<\/i> to pull up all of the various Swift-related settings.  We are interested in the <b>Swift Compiler &#8211; Custom Flags<\/b>, where you can specify <code>-DDebug -DStaging<\/code> for your <b>DebugStaging<\/b> configuration and <code>-DRelease -DProduction<\/code> for your <b>ReleaseProduction<\/b> build.  Once completed your <b>Build Settings<\/b> pane should look a bit like this:<\/p>\n<p><a href=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2014\/06\/swift_build_defines.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2014\/06\/swift_build_defines.png\" alt=\"swift_build_defines\" width=\"713\" height=\"504\" class=\"alignnone size-full wp-image-263\" \/><\/a><\/p>\n<p>Finally, which build configuration is used to build is driven by the <b>Scheme<\/b> you have selected, and how that scheme is configured.  Go to your schemes and create ones for <b>DebugStaging<\/b> and <b>ReleaseProduction<\/b> and set them to use the build configurations you&#8217;ve just created.  Now when you want to switch among them you can by simply changing your scheme.  For more information on build schemes, see our <a href=\"http:\/\/dev.iachieved.it\/iachievedit\/?p=37\">previous post<\/a> on the topic.<\/p>\n<p><a href=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2014\/06\/swift_build_scheme.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2014\/06\/swift_build_scheme.png\" alt=\"swift_build_scheme\" width=\"689\" height=\"246\" class=\"alignnone size-full wp-image-265\" \/><\/a><\/p>\n<p>As always, the source code for this blog post is available on <a href=\"https:\/\/github.com\/iachievedit\/buildconfigurations\">Github<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Editor&#8217;s Note: This post came out shortly after the release of Swift in 2014. It is not Swift 2.0-compliant, your mileage may vary! Well, that didn&#8217;t take long. Mere days after Apple introduced Swift someone has posted what they ostensibly hope to be a replacement for Cocoa Lumberjack. Not to be outdone, we&#8217;re introducing our [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[],"class_list":["post-256","post","type-post","status-publish","format-standard","hentry","category-swift"],"_links":{"self":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts\/256"}],"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=256"}],"version-history":[{"count":18,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts\/256\/revisions"}],"predecessor-version":[{"id":2554,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts\/256\/revisions\/2554"}],"wp:attachment":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/media?parent=256"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/categories?post=256"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/tags?post=256"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}