iOS Development Guide This development guide outlines the standards and the best practices that are adopted by the iOS team at 2359 Media. This is the first draft of the guide. We are eager for the feedback from our developers. Please feel free to create issues for any suggestions. Table of Contents Why This Is Required Objective-C Coding Conventions Swift Coding Conventions Project Technical Conventions Xcode CocoaPods Graphic Assets Groups Structure in Project Navigator Warnings Staging vs Production vs App Store Instruments Unit Testing SDK Compatibility Recommended Third-party Libraries for Objective-C Networking JSON Parsing Urban Airship (Device Registration) HUD Reachability Pull-to-Refresh Social Network UICollectionView on iOS 5.x Attributed Label Sidebar Menu (Hamburger UI) UIView (Nib Loading and Geometry Shortcuts) Page Control UIAlertView and UIActionSheet (Block-based wrappers) Recommended Third-Party Libraries for Swift Git Pull Request References Why This Is Required This guide should be considered as rules for first timers, but guidelines for experienced developers. Objective-C Coding Conventions Follow these two style guides: NYTimes Objective-C Style Guide 2359media fork of GitHub Objective-C Conventions Swift Coding Conventions Follow swift style guide from Raywinderlinch Raywinderlinch Swift Style Guide Project Technical Conventions Xcode Always use the most recent release version of Xcode. At the time of writing, the lastest version is Xcode 5. You can download it from Mac App Store or at Apple developer center . However, if a project still requires a base SDK of an old version of iOS, it'd handy to keep the lastest version of Xcode that supports the old SDK. For example, during the transition from iOS 6 to iOS 7, some legacy projects might not be ready to upgrade to iOS 7 SDK, because it would require a lot of effort to do so. In that case, we still need to keep Xcode 4.6.3 (and iOS 6 SDK) for these projects. Add old SDKs in new Xcode Each version of Xcode comes with only one SDK. For example, Xcode 5 comes with iOS 7.0 SDK while Xcode 4.6 comes with iOS 6.1 SDK. It's however possible to add iOS 6.1 SDK from Xcode 4.6 to Xcode 5. To do that, you simply copy the iOS 6.1 SDK folder inside Xcode 4.6 app bundle to the same position in Xcode 5 app bundle. Assuming you rename Xcode 4.6 app bundle to Xcode4.app , this is the command to do that: cp /Applications/Xcode4.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.1.sdk /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs If you prefer symbolic link instead of copying the entire folder, use this command: ln -s /Applications/Xcode4.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.1.sdk /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs CocoaPods Use CocoaPods to manage libraries. Don't copy library source files into the project. There is a repository of CocoaPods specifications ( podspec ): CocoaPods/Specs , which contains most of the common libraries. To add a library dependency, specify the name and the version. Library with podspec in CocoaPods/Specs pod 'AFNetworking', '2.0.0-RC3' You can also specify a library that is outside of CocoaPods/Specs. Library with podspec in the root of the repository. Either local repositories or remote repositories. pod 'AFNetworking', :path => '~/Documents/AFNetworking' pod 'AFNetworking', :git => 'https://github.com/AFNetworking/AFNetworking.git' If a library doesn't have a podspec , you can create a podspec on your own and host it in somewhere like gist.github.com , or even in a local folder. Library without podspec . Create podspec on you own. pod 'JSONKit', :podspec => 'https://raw.github.com/gist/1346394/1d26570f68ca27377a27430c65841a0880395d72/JSONKit.podspec' pod 'JSONKit', :path => '~/Documents/JSONKit.podspec' Graphic Assets Use Asset Catalogs in Xcode. Must include images for all sized. Use JPEG format for large images, e.g. background images. Talk to designer to optimize pngs before adding it to the Asset Catalog. Groups Structure in Project Navigator We recommend the project group structure as shown in the following screenshots. Assuming MyApp is the project name, we follow these conventions: Only 4 groups at the top level: MyApp , MyAppTests , Frameworks and Products . AppDelegate should be in the root level of MyApp , not inside any of its subgroups. MyApp has 8 subgroups: Storyboards : obviously storyboard files Models : all model classes, including Core Data classes and xcdatamodeld file Views : all custom views, e.g. custom table view cells controllers : all view controllers go here Managers : other controller-like classes that are not view controllers, for example, a http client class that handles all the API calls Categories : all categories Resources : resource files, like images, custom fonts or preloaded data Supporting Files : a default group with Xcode template No group for external libraries. Use CocoaPods to manage them. Use intent based grouping. For each intent, create a new group with all the corresponding files (viewControllers, views, storyboards, xib) inside it. For e.g if MyApp has Account and Products create two groups Account and Product under MyApp Each intent would've it's own storyboard. If Intent has multiple viewControllers, then each viewController would have it's own storyboard. Creating separate storyboards would prevent merge conflicts when developers are working on same stream. Warnings No warning is allowed in release builds. Treat warnings as errors. Staging vs Production vs App Store Use Xcode Scheme , Build Configuration and Build Settings to manage different builds, like staging build, production build or App Store build. Create Build Configurations. Both staging and production builds require Debug and Release configuration, while App Store only need Release configuration. As a result, we usually create 5 build configurations: Debug , Debug Staging , Release , Release Staging and App Store . Note that App Store is created by duplicating Release configuration. Add User-Defined Build Settings. Typically, we will create User-Defined Settings for Bundle ID, app icon names, Facebook App ID, etc. So we will be able to set different Bundle ID, icon names or Facebook App ID for different Build Configurations. These settings will be used in Info.plist. If the User-Defined Setting is FACEBOOK_APP_ID , you use it in Info.plist with ${FACEBOOK_APP_ID} . Create Schemes with Build Configurations. Each build needs one Scheme, so we will create 3 Schemes: MyAppStaging , MyAppProduction and MyAppAppStore , for staging build, production build and App Store build respectively. Note that these schemes should be marked "Shared", so that they will be added in the Git repository. MyAppStaging Scheme uses Debug Staging and Release Staging . Similarly, MyAppProduction Scheme uses Debug and Release , and MyAppAppStore Scheme uses only App Store . It's summarized in the followed table. After we have Schemes, we can, for example, switch to staging build by easily selecting MyAppStaging Scheme. Bundle ID, Facebook App ID and app icon will be changed automatically. In order to change the Base URL of API server for staging or production, we can implement a function that returns the correct URL based on Bundle ID. For example, the following function returns the staging Base URL if the Bundle ID has a prefix of com.2359media . NSString * MDABaseURL () { if ([[[ NSBundle mainBundle ] bundleIdentifier ] hasPrefix: @" com.2359media " ]) { return @" http://myapp-staging.2359media.net " ; } else { return @" http://myapp.2359media.net " ; } } Instruments Use Instruments to profile your app. For example, locating memory issues, analyzing CPU usage, mesauring I/O acitivity or graphics peformance. Resources for learning Instruments: Instruments User Guide WWDC 2010 Advanced Memory Analysis with Instruments WWDC 2010 Advanced Performance Analysis with Instruments WWDC 2011 iOS Performance and Power Optimization with Instruments WWDC 2011 iOS Performance in Depth WWDC 2012 Learning Instruments WWDC 2012 iOS App Performance: Responsiveness WWDC 2012 iOS App Performance: Graphics and Animations WWDC 2012 iOS App Performance: Memory WWDC 2013 Fixing Memory Issues WWDC 2013 Core Data Performance Optimization and Debugging Unit Testing Create unit tests for critical code. Especially, test the following cases: Complex code that have many edge cases to consider. Write unit tests to cover these edge cases. Whenever a bug is found, write a unit test to cover it before fixing the bug. Resources for getting started with unit testing in Xcode : Unit Test Your App WWDC 2014 Testing in Xcode 6 Use the following 3rd party libraries if you want to do BDD style testing. Quick Nimble SDK Compatibility It's quite often that we need to support older iOS versions. There are few ways to do this: From Apple Documentation's SDK Compatibility Guide . From a more simplified article in Ray Wenderlich's Supporting Multiple iOS Versions and Devices . But, the most obvious way is by checking the Foundation framework version number: if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1) { // Handle the case for iOS 6.1 or earlier } else { // Handle the case for iOS 7 or later } Also, make sure to read Supporting iOS 6 in iOS 7 UI Transition Guide. Recommended Third-party Libraries for Objective C Here are a list of libraries that are widely used in our projects. Developers are recommended to choose the listed library for that particular feature. If, however, developers want to use a different library or experiment a new library. Please create a new issue to argue that why an alternate library is better. Networking AFNetworking by Mattt Thompson A delightful iOS and OS X networking framework. http://afnetworking.com AFNetworking 2.0 officially supports iOS 6+, Mac OS X 10.8+, and Xcode 5. If you'd like to use AFNetworking in a project targeting a base SDK of iOS 5, or Mac OS X 10.7, use the latest tagged 1.x release. For iOS 4.3 and Mac OS X 10.6 support, use the latest tagged 0.10.x release. JSON Parsing NSJSONSerialization (iOS 5+) JSONKit by John Engelhart A Very High Performance Objective-C JSON Library Urban Airship (Device Registration) AFUrbanAirshipClient by Mattt Thompson An API Client for Registering and Unregistering Devices with Urban Airship. HUD SVProgressHUD by Sam Vermette A clean and lightweight progress HUD for your iOS app. http://samvermette.com/199 Reachability Reachability by Tony Million ARC and GCD Compatible Reachability Class for iOS and MacOS. Drop in replacement for Apple Reachability. Pull-to-Refresh UIRefreshControl (iOS 6+) SVPullToRefresh by Sam Vermette Give pull-to-refresh & infinite scrolling to any UIScrollView with 1 line of code. http://samvermette.com/314 Social Network UIActivityViewController Use system sharing sheet, so no custom UI is allowed. Use it whenever possible. Social.framework (iOS 6+) Twitter.framework (Twitter only and iOS 5 only, deprecated in iOS 6) Facebook SDK for iOS by Facebook Use it for everything related to Facebook, including Facebook login, Facebook sharing, user profile, friend list, etc. UICollectionView on iOS 5.x PSTCollectionView by Peter Steinberger Open Source, 100% API compatible replacement of UICollectionView for iOS4.3+ Attributed Label TTTAttributedLabel by Mattt Thompson A drop-in replacement for UILabel that supports attributes, data detectors, links, and more Sidebar Menu (Hamburger UI) MMDrawerController by Mutual Mobile A lightweight, easy to use, Side Drawer Navigation Controller UIView (Nib loading and Geometry shortcuts) ViewUtils by Nick Lockwood ViewUtils is a collection of category methods designed that extend UIView with all the handy little properties and functionality that you always wished were built-in to begin with. Page Control DDPageControl by Damien DeVille An easily customizable alternative to UIKit's UIPageControl UIAlertView and UIActionSheet (Block-based wrappers) PSAlertView by Peter Steinberger Modern block-based wrappers for UIAlertView and UIActionSheet. Recommended Third Party Libraries for Swift Alamofire HTTP networking library written in Swift. SwiftyJSON JSON parser in Swift. PureLayout AutoLayout utility library. Git We use Git as our source code management (SCM) system. We host repositories in GitHub. Here are the best practices of using Git and GitHub. Commit early and commit often. Don't change published history. Particularly, don't rebase remote branch. Once you git push your changes to the authoritative upstream repository or otherwise make the commits or tags publicly visible, you should ideally consider those commits etched in diamond for all eternity. Use git-flow. Gitflow is a Git workflow that Vincent Driessen introduced in his post A successful Git branching model . In addition to that, he released git-flow , which is a collection of Git extensions to provide high-level repository operations for his branching model. Write good commit messages. Here's a model Git commit message: Capitalized, short (50 chars or less) summary More detailed explanatory text, if necessary. Wrap it to about 72 characters or so. In some contexts, the first line is treated as the subject of an email and the rest of the text as the body. The blank line separating the summary from the body is critical (unless you omit the body entirely); tools like rebase can get confused if you run the two together. Write your commit message in the imperative: "Fix bug" and not "Fixed bug" or "Fixes bug." This convention matches up with commit messages generated by commands like git merge and git revert. Further paragraphs come after blank lines. - Bullet points are okay, too - Typically a hyphen or asterisk is used for the bullet, preceded by a single space, with blank lines in between, but conventions vary here - Use a hanging indent Read Tim Pope 's post A Note About Git Commit Messages for more discussions. Integrate Pivotal Tracker. If a commit has related Pivotal Tracker stories, use Pivotal Tracker post-commit hooks to link the commits to the particular stories. For all the details, including commit syntax as well as instructions on how to enable SCM integration, please see the API help page . Here're some typical commit messages that include Pivotal Tracker post-commit hooks: [#53928321] Create editorial page [Fix #55789490] "$" sign appears in a wrong position [Finish #53870315] Update icons for review buttons Also see Commit Often, Perfect Later, Publish Once: Git Best Practices for more discussions. Pull Request We use Pull Requests to initiate code review and genenral discussion about changes before being merged into a main branch. We follow the maintainer/contributors workflow . The tech lead of each project is the maitainer, who will review the pull requests submitted by the contributors before merging them into the main branch. The reset of developers in the team are the contributors, who will submits their changes through pull requests. References iOS Developer Library is where you can find all the programming guides , class references , sample code , videos , etc. NSBlog by Mike Ash . objc.io by Chris Eidhof , Florian Kugler and Daniel Eggert . NSHipster by Mattt Thompson . @phatle collects a huge number of references in his iOS Topics and References , and they are grouped by topics for easily looking up. It's a handy document for developers who just start out iOS development.