Three20 Migration Guide

Getting Started

If you've added Three20 to one of your projects then you're undoubtedly familiar with the incredible overhead of the framework's size and work involved in tweaking project settings. While the concept of shared static libraries has its benefits, the reality is that most applications are standalone entities and it is rare that you would be switching between applications rapidly enough to justify the shared build times.

Nimbus reduces build times by throwing this model out the window altogether and being truly modular. When you add Nimbus to your project, you only add the code for the features you want to use, and you add this code directly to your project. With Nimbus, you only need to manage one project's settings, one target for your application, and zero dependent static libraries (unless you're using a non-Nimbus library of course). This also means that if there is a feature within Nimbus that you've already built or included in your app (ASIHTTPRequest), for example, then you can simply use that code and modify it as you wish.

The Nimbus Namespace

The Nimbus namespace is an NI prefix to all types and functions. Three20's is TT. Quite often Three20 features will exist in Nimbus as well. When this is the case, you simply have to replace the TT prefix with NI.

Using Nimbus Alongside Three20

It is possible for both frameworks to exist in one application because the two frameworks use different prefices. This has the obvious downside of only increasing the size of your application, but as Nimbus develops the benefit of replacing certain features with Nimbus equivalents may prove worth the cost. In the future it is hoped that Nimbus will reach feature parity with Three20, at which point you would be able to remove Three20 from your project altogether.

Features That Map One-to-One

Certain features map from Three20 to Nimbus directly. You can begin using these features by doing a global find and replace in your application's code.

Debugging Tools

Three20                         Nimbus
-----------------------------   --------------------------------------
TTDASSERT()                     NIDASSERT()
TTDCONDITIONLOG()               NIDCONDITIONLOG()
TTDPRINT()                      NIDPRINT()
TTDPRINTMETHODNAME()            NIDPRINTMETHODNAME()
TTDINFO()                       NIDINFO()
TTDERROR()                      NIDERROR()
TTDWARNING()                    NIDWARNING()

Device Orientation

Three20                         Nimbus
-----------------------------   --------------------------------------
TTIsSupportedOrientation()      NIIsSupportedOrientation()

Network Activity

Three20                         Nimbus
-----------------------------   --------------------------------------
TTNetworkRequestStarted()       NINetworkActivityTaskDidStart()
TTNetworkRequestStopped()       NINetworkActivityTaskDidFinish()

Preprocessor Macros

Three20                         Nimbus
-----------------------------   --------------------------------------
__TT_DEPRECATED_METHOD          __NI_DEPRECATED_METHOD
TT_FIX_CATEGORY_BUG()           NI_FIX_CATEGORY_BUG()

Three20 Features Deprecated by Nimbus Features

Some features built for Nimbus completely deprecate closely related Three20 features. To switch from using the Three20 feature to the Nimbus equivalent may require some extra work beyond a simple find-and-replace. Where possible the architectural differences are noted below to aid in the transition process.

In-Memory Caching With TTURLCache

Nimbus provides NIMemoryCache for caching objects in memory. It is designed only for storing objects in memory and does not provide disk caching. This is by design: touching the disk should be an explicit activity so that the performance implications are obvious. TTURLCache was not clear on how it accessed the disk cache.

Due to this design choice, one of the primary differences between NIMemoryCache and TTURLCache is the fact that NIMemoryCache does not provide a disk cache. You can't use an NIMemoryCache to store or load images from disk.

TTURLCache is primarily used for caching images. It uses a fake, least-recently-used cache removal algorithm where images are removed in the same order that they were added to the cache. This can lead to unexpected cache misses when the cache is used heavily and images start being removed even though they were recently used.

NIImageMemoryCache solves this problem by taking advantage of the true least-recently-used cache removal algorithm built into NIMemoryCache. Whenever an image is accessed it moves to the end of a linked list. When the cache limit is reached or a memory warning is received, images are removed from the front of the linked list until the memory constraints are satisfied.

Global Singletons

Three20 implements singletons directly in the class that provides the singleton implementation. This places too much emphasis on the fact that the object is meant to be used as a singleton, so Nimbus avoids this practice.

Instead, Nimbus provides access to singletons via the global Nimbus state object. You'll notice that Nimbus is highlighted as a link throughout the documentation, this is because Nimbus is a class within the Nimbus framework. To access singletons, you call class methods on Nimbus.

For example, to access Nimbus' equivalent to TTURLCache, you use [Nimbus imageMemoryCache].

Network Images with TTImageView

Three20's network image view is completely deprecated by Nimbus' NINetworkImageView. Three20's network image view is an overly complicated TTView object with too many non-critical features built in. NINetworkImageView, on the other hand, is a simple UIImageView view.

NINetworkImageView is incredibly efficient when it comes to using memory. Where TTImageView would download an image and them simply crop and resize the image whenever the view was drawn, NINetworkImageView crops and resizes the image on a separate thread and then draws the image without any scaling required. The image stored in the memory cache is also much smaller as result. Performance is noticeably improved when many image views are on the screen at once. A good example would be flipping through a friend list on the iPad with large, high-resolution images laid out in a grid.

NINetworkImageView also handles retina displays more intelligently than TTImageView by creating scaled UIImages.

Photo Albums with TTPhotoViewController

Three20's photo album viewer was built around the time iOS 3.0 was first coming out. Take a second to let that sink in, because that was a hell of a long time ago by the iOS SDK's standards.

Around that time the scroll view implementations were certainly lacking some of the nice features required by a photo viewer. As a result, Three20 included a from-the-ground-up implementation of TTScrollView. This is no longer necessary and the new Nimbus photo viewer rejoices in the use of native UIScrollViews.

Three20's photo viewer was also incredibly entrenched in the Three20 network model battleground with no hope of salvation. Nimbus' photo viewer is built using a light-weight, completely independent data source/delegate design that is similar in principle to UITableView.

Instead of using a TTPhotoViewController, you can now use an NIToolbarPhotoViewController. All you are required to do is implement the data source methods. Examples of such implementations can be found in the network photo album sample app.

Nimbus photo viewer is faster, performs better under low-memory conditions, uses native scroll views and has an overall lower memory footprint. It also encourages processing data on separate threads instead of in the main UI thread like Three20's network stack does.

Web Views with TTWebController

Three20's web controller is one of the most popular controllers used in the Three20 framework. It is tied to the UI, UINavigator, UICommon, Style, Network and Core libraries though which meant that you had to pull in the entire Three20 framework just to use the web controller.

NIWebController's only dependency is the Nimbus Core and it a direct subclass of UIViewController. This makes it is remarkably easy to add the web controller to any project with minimal overhead.