Crush & Lovely's iOS boilerplate.
We want to hit the ground running. Xcode and the iOS ecosystem don't make that easy. Enter Amaro. After running one simple command, you get a ready-to-build universal iOS application, full of delights.
Change to your projects directory, run this line in your terminal, and follow the prompts:
ruby -e "$(curl -fsSL https://raw.github.com/crushlovely/Amaro/master/tiramisu)"
Of course, if you're wary of running random scripts (legit!), please read tiramisu. At a high level, the script creates a local git repository with Amaro as a remote named "bootstrap", tweaks filenames and contents as per your input, and grabs third-party code from Cocoapods.
(Tiramisu is Italian for "pick me up". Bootstrap... pick me up... get it?!? 💃)
The bootstrap assumes:
- You are using Xcode 5 or later.
- You have version 0.34.1 or later of the CocoaPods gem installed.
- You are on OS 10.9 or later
- You are targetting iOS 7.0, at minimum (and thus will be compiling against at least the iOS 7.0 SDK).
- As of July 2014, iOS 7 has an 90% adoption rate.
And, optionally:
- Sass/
.scss
support requires the Sass command line tool to be installed.
Want to use Swift? Amaro won't stop you, but note that CocoaPods support for third-party Swift projects is still pending. See this issue for details and future plans.
Amaro aims to set you up with all you need to write a beautiful, maintainable, well-tested app. All the default pods are optional; feel free to pick and choose as needed for your project (though you will probably want most of them).
- A well-chosen class prefix is enforced (or may be omitted entirely... the times, they are a-changin')
- A local git repository for the application is created (and committed to a few times through the initialization process).
- A sane
.gitignore
file is included. - A
Certificates
directory is included with a readme file about what to include so that other developers can test and release the app. - Sensible defaults for build options, warnings, and the like.
- Build configurations are split into xcconfig files for modularity and consistency. We're using jspahrsummers/xcconfigs as our base.
- There are separate staging, production, and distribution schemes, and corresponding preprocessor macros. No more fiddling with variables here and there to switch your target environment.
- Automatic ways to easily distinguish between builds of the app:
- Ad-hoc and development builds have their bundle id suffixed with ".adhoc" or ".dev" so that they can co-exist on devices with other builds.
- Ad-hoc and development builds' icons are badged with an 🅢 for staging environments and a 🅟 for production environments. The bundle names (but not the display names) are also changed to easily distinguish them in places where it may otherwise be difficult.
- The build number of the app is incremented on every ad-hoc and distribution build. This ensures that external distribution services can reliably distinguish builds, even if the version number itself doesn't change.
- CocoaPods are integrated from the get-go.
- A barebones settings bundle is included with an "Acknowledgements" section that includes licenses for all your pods. It's automatically updated after each
pod install
. - Identifiers from storyboards and asset catalogs are pulled out into constants, much like objc-codegenutils.
- CocoaLumberjack is configured for logging. A custom formatter is used by default to include the class and method name in log messages.
- The Crashlytics framework is included, and tied into CocoaLumberjack via CrashlyticsLumberjack so that high-importance log messages are sent to Crashlytics.
- Aperitif, to check for updates of the app in Installr and prompt the user to install them (in ad hoc builds only, obviously).
- Specta, Expecta, and OCMokito are included to allow for the creation of Rspec-like tests. Xcode integration for testing is fully configured; add your tests to the Specs target and hit Cmd+U.
- The test target automatically generates code coverage data that can be viewed with Cover Story or gcov.
- Pixate Freestyle, for easy, centralized app styling via CSS.
- SCSS files included in the project are automatically compiled at build-time, and only the resulting CSS is included in your app. This functionality requires that Sass be installed and available in your path (or in your default RVM configuration's path).
- AFNetworking
- libextobjc's scope and keypath checking modules.
- FormatterKit, for all your string-formatting needs.
- Asterism, a fast, simple and flexible library for manipulating collections.
- Sidecar, Crush's homegrown library. Features commonly needed functionality, such as creating UIColors from hex, playing short sound effects, and performing blocks on the main thread.
Additionally, the Podfile notes a few optional libraries that you may find useful:
- PromiseKit, a promises/futures library similar to Promises/A+, and related wrappers for core libraries.
- Mantle, a project from the GitHub folks to make simpler, safer model classes.
- SSKeychain, a friendly wrapper around the Keychain API.
- DateTools, if you find yourself needing to do a lot of datetime math.
- OHHTTPStubs, to stub out responses from web services for testing or early in development.
Amaro will get you started on the right foot, but it's up to you not to mess it up! Here are some tips to stay in line with the spirit of the project.
Read up on the included and optional libraries. Most of them are very good at solving common problems, and you should become familiar with them. Ideally you should spend your time solving problems, not solving problems around solving problems.
Here are some specific tips:
- Making a change to a build setting? Make it once in your project's
.xcconfig
file, so that it will propagate to all configurations. - Adding an external library? If there's a podspec for it, bring it in via Cocoapods. If there's not, consider writing one and submitting it upstream. Use git submodules as a last resort; version and dependency management with them is a pain in the ass.
- There should almost never be a reason to check in third-party projects wholesale. If you need to modify someone else's code, fork the repo and include the fork in your Podfile with a direct
:git
reference.
- There should almost never be a reason to check in third-party projects wholesale. If you need to modify someone else's code, fork the repo and include the fork in your Podfile with a direct
- Use CocoaLumberjack's
DDLog
variants instead ofNSLog
. It's faster, provides more information, is more configurable, and understands log levels. All of that with the same familiar syntax. Retrain your fingers. - Need to define different settings in staging and production? Check out the ProjectName-Environment.h file in Other Sources. It defines macros to test the type of build that is currently taking place.
- Make friends with Pixate Freestyle. We've yet to have much experience with it in the real world, but it seems pretty damn amazing. Check out the samples to see what I mean.
The real content and value of Amaro is as a template; once you've created a new project with the initialization script, Amaro leaves barely a trace. So, in most cases, the only licenses you need to worry about are those of the third-party software you've included. But anyway, should you want to deal with Amaro itself, it's MIT licensed:
Copyright (c) 2014 Crush & Lovely, LLC
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
As mentioned above, the bootstrap automatically generates a settings section containing license information for all your Cocoapods. If that's unacceptable for your purposes, here's the license information on the included and optional components:
- Pixate Freestyle: Apache 2 -- requires a copy of the license somewhere in the distribution
- Crashlytics Framework: Terms and Conditions
- CrashlyticsLumberjack: BSD 3-Clause -- see this StackOverflow discussion about the implications of this for iOS applications (short version: consensus seems to be "do what you will", but the official word is unclear).
- CocoaLumberjack: standard BSD
- AFNetworking: MIT
- extobjc: MIT
- FormatterKit: MIT
- Asterism: MIT
- PromiseKit: MIT
- Mantle: MIT
- SSKeyChain: MIT
- DateTools: MIT
- Sidecar: MIT
- Aperitif: MIT
Once upon a time there was a similar project, but it seems to have been abandoned. More recently, the lovely folks at thoughtbot released liftoff. Amaro takes a different tack than liftoff: more opinions, less scriptability. Check it out for an alternative take on the problem.
Know of anything else in the realm? Drop us a line! We'd love to hear about it and see how others are tackling things.
The lovely icon was created by Ray Bruwelheide. It is licensed under the Creative Commons Attribution 3.0 license.