Skip to content
Samuel Défago edited this page Nov 28, 2014 · 10 revisions

Introduction

CoconutKit is a library of rock-solid components with clean, simple and well-documented interfaces. These components are meant to make you more productive by eliminating most of the boilerplate code you need to write every day as an iOS developer, filling many gaps left open by iOS system frameworks.

Most notably, CoconutKit components will help you with:

  • View controller management and containment
  • Displaying data and gathering input from the user
  • Localization
  • Core Data management
  • Animations
  • ... and much more

CoconutKit is a library, not a framework: You are free to use whichever components you need, and to ignore those which are of no help. You do not need to conform to complicated abstract protocols, or to write your code according to specific and rigid conventions. You do not need to learn any new fancy syntax, or complicated obscure macros which are a nightmare to debug. Code using CoconutKit just looks like the Objective-C that iOS developers so much love.

The following briefly describes which kind of components you will find in CoconutKit, and why you should consider using them. For more information and examples of use, refer to the dedicated wiki topics.

View controller management and containment

UIKit provides you with a limited number of ways with which you can manage your view controller hierarchy, most notably:

  • UITabBarController
  • UINavigationController
  • UISplitViewController
  • Modal view controllers

If you want to do something fancier, or even simple things like presenting a modal view controller on the iPhone while still seeing the view controller underneath, maybe using non-standard animations, you are usually on your own. Usually, this means you will need to manage your view controller hierarchy yourself. Trust me, if you are doing it already in your applications, even using the iOS 5 containment API, you are probably doing it wrong: Managing a view controller hierarchy correctly is very difficult to get right.

This is why CoconutKit provides you with robust view controller containers, with which you will be able to create and manage view controller hierarchies like never before:

  • HLSPlaceholderViewController, which lets you embed an arbitrary number of child view controllers into a view controller
  • HLSStackController, which lets you manage a stack of view controllers

Both containers support nesting, storyboards, and are fully compatible with UIKit standard containers. You can display child view controllers using a rich set of built-in animations, and even provide your own transition animations if none of the built-in ones suits your needs. These containers have in fact far more capabilities than UIKit built-in containers, and will help you write better applications. Ultimately, you will namely be able to split up your applications into separate view controllers, each with clearly defined responsibilities. This provides you with the ability to reorder your view controller hierarchy very easily, something you cannot achieve if you are managing your view controllers manually.

All CoconutKit containers are implemented using an underlying view controller stack management class, HLSContainerStack, which is public as well. This class provides a complete API with which you will be able to implement any kind of view controller container easily, without ever having to worry about the many issues related to view controller containment.

CoconutKit containers are the result of two years of hard work, and deal with all intricacies of view controller containment. Believe me, if you think you have written a correct view controller containers in a few days or weeks, you are probably wrong. There are too many issues you must deal with, like event forwarding, rotation, view resizing, root and modal view controllers, view controller pre-loading, proper resource management, parent - child relationship management, compatibility with UIKit containers, discrepancies between iOS versions, etc. This is definitely a complexity you want to be able to forget.

Refer to the containers wiki page for more information.

Core Data management

Core Data is a wonderful framework. In too many projects I worked on, I started with a custom lightweight object model fulfilling exactly my needs. As usual, I then discovered I needed a way of requesting objects, persisting them or checking their consistency. And in all cases, I ended up rewriting part of Core Data, regretting not to have used it right from the start.

You should never make the same mistakes as I made. Even if you do not need all of Core Data features at the time you start a project, you can be sure that Core Data will save you a lot of time and headaches later. You just need a few model objects, nothing more? Well, that's not a reason not to use Core Data and an in-memory persistent store, which lets your conveniently design your model using the Xcode Core Data editor. When you later discover that your objects must finally be persisted on disk, all that is basically required is to change a single setting.

There are usually a few issues when working with Core Data, though:

  • There is a lot of boilerplate code to write, and the Xcode Core Data template is rather poor
  • The code becomes cluttered with managed object contexts, and issues can arise in multi-threaded applications if you use the wrong context by mistake
  • Validation is poorly implemented and leads to a lot of boilerplate code (e.g. for proper error-chaining), especially if you want to perform validation both interactively (when a model field is edited using a text field) or when an object is saved to the persistence store

To solve all those issues, CoconutKit provides with:

  • HLSModelManager, a class which manages context and persistence store creation for you. No more Xcode templates to use, everything has been done once for all. To eliminate issues with explicit managed contexts thrown all over the place, you now never interact with managed contexts directly. Instead, stacks of HLSModelManager objects are managed on a thread basis. Context-free methods then allow you to perform usual CRUD operations with the managed object context associated with the top model manager only.
  • A validation runtime layer, which makes it possible to write validation methods once for all in a single place, and to call them both interactively and when saving objects to the store. Error-chaining has also been implemented correctly and consistently

Animations

Animations are a perfect way to create intuitive and fluid user interfaces and, ultimately, beautiful applications which your users strive to use and love to look at. Sadly, code can become quite a nightmare to write and maintain when you want to create non-trivial animations:

  • Chaining animations leads to spaghetti code: If you want to chain two animations, you need to start the second animation in the end callback or in the completion block of the first one. This of course becomes a mess as more animations are wired together, and is a pain in the ass when you are tweaking complex animations
  • If you want to play some fancy animation backwards (e.g. a complex animation which displays a menu), you need to reverse all animation parameters manually (and correctly!), and chain corresponding reverse animations. Your code becomes even messier than before. Moreover, when tweaking the normal animation, you of course have to update the code of the reverse animation as well
  • UIView block-based animations and Core Animation layer-based animations are created using different approaches (though UIView-block based animations are ultimately implemented using Core Animation)
  • There is no clean interface to pause, resume or cancel an animation once it has started. Moreover, running animations are removed and restarted when an application is sent to the background, which is quite ugly and can lead to bugs which are difficult to fix

To solve all above issues, CoconutKit introduces the HLSAnimation class, which offers the following features:

  • A declarative way to create animations: An animation is created in a single place. No more delegate method chaining, no more spaghetti code to write. Tweaking animations has never been easier
  • A way to combine UIView block-based animations and Core Animation layer-based animations using a unified formalism
  • A convenient interface which lets you play animations (also instantaneously), pause and resume them, start them at abritrary times, delay them, or create animation loops. A delegate can be registered to receive detailed information about the animation status
  • A correct behavior when the application is sent to and restored from the background

Localization

Usually, users change the language of an application by opening the system preferences and changing their device language, which is a rather slow and inconvenient process. Wouldn't it be nice if users could change the language at runtime, without the need to leave the application?

Fortunately, CoconutKit provides you with a way of localizing applications so that the language can be changed at runtime (the language can still be changed in the system settings if your prefer). This is achieved by having your view controllers collect their localization code in a single method, which is called at runtime as soon as a language change notification is received.

Now, how do you localize an application? There are usually three approaches:

  • Create and maintain separate nib files, one for each language
  • Create a single nib file, and generate localized versions by running a command-line tool during the build process
  • Create a single nib file, and get it localized by binding outlets and setting texts programmatically

The first approach is the shortest way to disaster and should be avoided. The second option is better, but if we want to stay compatible with CoconutKit ability to change the language at runtime, we cannot apply it, since there is no way to seamlessly switch between nibs at runtime. Localization must be therefore be made in code, and the third approach must be applied.

This usually comes at a price: The code becomes cluttered with outlets defined only for localization purposes. To solve this problem, CoconutKit introduces a way to localize labels and buttons directly in nib files, using a set of reserved prefixes, without requiring any outlet to be defined.