Blog posts

Disabling App Transport Security in your development environment

iOS 9 introduced App Transport Security, which by default forces apps to communicate over HTTPS instead of HTTP. This is a great default for production apps, but it can get in the way of connecting to development servers which are less likely to be configured with a HTTPS connection, especially when running on your local machine.

To get around this an exception can be added for localhost (or any other known development environment domain) which will allow your app to send and receive unencrypted HTTP requests. In your Info.plist add the following:

<key>NSAppTransportSecurity</key>
<dict>
  <key>NSExceptionDomains</key>
  <dict>
    <key>localhost</key>
    <dict>
      <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
      <true/>
      <key>NSIncludesSubdomains</key>
      <true/>
      <key>NSExceptionAllowsInsecureHTTPLoads</key>
      <true/>
    </dict>
  </dict>
</dict>

If you’re editing your Info.plist visually in Xcode, you should have these entries:

App Transport Security info.plist screenshot

Swift: A nicer way to tell if your app is running in Debug mode

Often while working on an iOS app there’s functionality that you want exposed only when the app is running in a Debug build configuration. Previously I would use build environment variables and preprocessor macros to determine this, but thanks to the great answer on this Stack Overflow question I now use a runtime check to tell whether the app is running in Debug or Release mode:

// Returns true if the app is running in a Debug build
_isDebugAssertConfiguration() -> Bool

// Returns true if the app is running in a Release build
_isReleaseAssertConfiguration() -> Bool

// Example usage: only printing to the log when the app is running in Debug
if _isDebugAssertConfiguration() {
  print("Log: User \(user) logged in")
}

Note: these functions aren’t publicly documented in Swift’s API, and are only available from Swift 2.1 onwards. As kennytm says in his Stack Overflow answer, there is a risk of this function being removed in a future update.

If you do want to use this in your codebase, I have created a convenient helper around the function in my Swift helper library: APSwiftHelpers.

Development environment config overrides in Jekyll

While building this website using Jekyll I found that there were a few places where I needed to override config variables when the site is running in a development environment. Some examples of dev only overrides I wanted to do are:

  • Skip minifying the SASS output so it’s easily debuggable
  • Show all draft posts by default
  • Run the server on port 4000, accepting all incoming connections

The best way I found to do this was by having two config files; a base config used in production (_config.yml), and an override config used only in development (_config_dev.yml):

# _config.yml - Base config used in production

sass:
  style: compressed

show_drafts: false
# _config_dev.yml - Dev environment configs and overrides

show_drafts: true

# Accepts connections on port 4000 from any source
host: 0.0.0.0
port: 4000

# Don't compress SASS output
sass:
  style: full

As you can see, any dev-specific config options just need to go into the _config_dev.yml file. This can be a Jekyll option you need to override, or an option for any of your Jekyll plugins.

To launch the Jekyll server in a dev environment I then run the following command

  • note that _config_dev.yml must be specified last so that its config items override _config.yml.
$ jekyll serve --config "_config.yml,_config_dev.yml"

This command will first load in the normal config, and then the dev only overrides. To make this even easier to launch I put the command under a script/dev file so I can launch it without having to type out the names of both the config files. You can see an example of this in my repo for this website.

Since I’m deploying this using GitHub pages I didn’t need to do anything extra to have this working in production. GitHub pages compiles Jekyll using the _config.yml file by default and ignores all other config files, but if your deployment is slightly different all you’d need to do is exclude the _config_dev.yml from the jekyll build command when doing your Jekyll build, and you should be good to go!