Home

Awesome

Version License Platform

iOS Project bootstrap

How do you setup your iOS projects?

Since we are approaching 2015 I’m working on refreshing my project bootstrap. I’ve decided to open source it so other can benefit or contribute.

I think it’s pretty neat but decide for yourself.

It’s still WIP so pull requests are most welcomed.

Basic setup and configuration

A project by default has 3 configurations:

  1. Debug
  2. Release
  3. Adhoc

Each configuration can be put side by side on same device, and you can clearly distinguish each build. Easier to find issues across different versions and branches.

Looking at each of the icon you get following informations:

You can also use KZBootstrap API to query those informations while running your application.

Code Quality and Warnings

Warnings were added by compiler team for a reason, as such I start with Weverything and disable few warnings:

Also treat warnings as errors is a must.

That’s not all, let’s add some scripts:

	#if merowing
	//! my code
	#endif 

One more thing, let’s add some macros: To prevent nil passed in as arguments:

When your subclasses should call super:

When you want to avoid spelling errors:

Environments

Often when working with big clients, you need to have multiple environments for Staging / Production / QA etc. They usually differ in some kind of configuration, eg. different URL endpoints.

Too many times I’ve seen people creating separate targets for each of them, which leads to maintenance costs and unnecessary bloat/clutter.

As such I’ve created a different approach, with some nice automation:

Logging - Optional

If you are using CocoaLumberjack you can include KZBootstrap/Logging subspec to get log formatting that works as clickable links in AppCode.

Debugging - Optional

If you decide to include KZBootstrap/Debug subspec, you will get:

[KZBResponseTracker printAll]

Installing KZBootstrap

KZBootstrap is available through CocoaPods. To install it, simply add the following line to your Podfile:

There are few things you need to do with your project, you can either use my crafter setup tool to make it automatic or do it manually:

Base crafter setup might look like this, replace CUSTOM with your preferred steps:

# All your configuration should happen inside configure block
Crafter.configure do

  # This are projects wide instructions
  add_platform({:platform => :ios, :deployment => 7.0})
  add_git_ignore
  duplicate_configurations({:adhoc => :release})

  # set of options, warnings, static analyser and anything else normal xcode treats as build options
  set_options %w(
    RUN_CLANG_STATIC_ANALYZER
    GCC_TREAT_WARNINGS_AS_ERRORS
  )

  set_build_settings({
    :'WARNING_CFLAGS' => %w(
    -Weverything
    -Wno-objc-missing-property-synthesis
    -Wno-unused-macros
    -Wno-disabled-macro-expansion
    -Wno-gnu-statement-expression
    -Wno-language-extension-token
    -Wno-overriding-method-mismatch
    ).join(" ")
  })

  set_build_settings({
    :'BUNDLE_ID_SUFFIX' => '.dev',
    :'BUNDLE_DISPLAY_NAME_SUFFIX' => 'dev',
    :'KZBEnv' => 'QA'
  }, configuration: :debug)

  set_build_settings({
    :'BUNDLE_ID_SUFFIX' => '.adhoc',
    :'BUNDLE_DISPLAY_NAME_SUFFIX' => 'adhoc',
    :'KZBEnv' => 'QA'
  }, configuration: :adhoc)

  set_build_settings({
    :'BUNDLE_ID_SUFFIX' => '',
    :'BUNDLE_DISPLAY_NAME_SUFFIX' => '',
    :'KZBEnv' => 'PRODUCTION'
  }, configuration: :release)
  
  # CUSTOM: Modify plist file to include suffix and displayname
  # CUSTOM: Add empty KZBootstrapUserMacros.h file to your project and .gitignore
  # CUSTOM: Add KZBEnvironments.plist with list of your environments under KZBEnvironments key

  # target specific options, :default is just a name for you, feel free to call it whatever you like
  with :default do

    # each target have set of pods
    pods << %w(KZAsserts KZBootstrap KZBootstrap/Logging KZBootstrap/Debug)
    
    # add build script for bootstrap
    scripts << {:name => 'KZBootstrap setup', :script => '"${SRCROOT}/Pods/KZBootstrap/Pod/Assets/Scripts/bootstrap.sh"'}

  end
end

In you want to support dynamic env switching app delegate you can add something like this:

 NSLog(@"user variable = %@, launch argument %@", @"d", [[NSUserDefaults standardUserDefaults] objectForKey:@"KZBEnvOverride"]);
  KZBootstrap.defaultBuildEnvironment = KZBEnv;
  KZBootstrap.onCurrentEnvironmentChanged = ^(NSString *newEnv, NSString *oldEnv) {
    NSLog(@"Changing env from %@ to %@", oldEnv, newEnv);
  };
  [KZBootstrap ready];
  
  NSLog(@"KZBootstrap:\n\tshortVersion: %@\n\tbranch: %@\n\tbuildNumber: %@\n\tenvironment: %@", KZBootstrap.shortVersionString, KZBootstrap.gitBranch, @(KZBootstrap.buildNumber), KZBootstrap.currentEnvironment);

License

KZBootstrap is available under the MIT license. See the LICENSE file for more info.

Author

Krzysztof Zablocki, krzysztof.zablocki@pixle.pl

My blog

Follow me on twitter.

Attributions

All of this wouldn’t be possible if we didn’t have such a great community, based on my own previous work but also countless others. Tried to reference everything but if you think I missed something please let me know.

References:

http://stackoverflow.com/questions/10497552/how-to-configure-independent-sets-of-runtime-settings-in-xcode

https://github.com/crushlovely/Amaro

https://github.com/crushlovely/Sidecar

http://swwritings.com/post/2013-05-20-concurrent-debug-beta-app-store-builds

https://gist.github.com/dulaccc/a52154ac4c007db2be55

https://gist.github.com/steipete/5664345

http://blog.manbolo.com/2013/05/17/passing-user-variable-to-xcodebuild

http://blog.jaredsinclair.com/post/97193356620/the-best-of-all-possible-xcode-automated-build

https://github.com/krzysztofzablocki/crafter

https://github.com/krzysztofzablocki/IconOverlaying

Big thanks goes to Lextech Global Services for supporting my community work, they are awesome. If you need a mobile app for your enterprise, you should talk to them.