Contentful SDK for iOS

April 4, 2014


We are excited to share with you some great news! Today we are officially announcing the availability of the iOS SDK for Contentful. The arrival of the SDK should make it very straightforward to integrate the Contentful API and to distribute your content to iOS apps.

Read on to find out what our iOS SDK does and how you can use it to build content-driven apps more easily. The coffee guide app from our recent hackathon will provide an example and walk you through building a simple app from start to finish.


There are three different ways for integrating the SDK into your own apps, described in detail in the README. For the purpose of this article, we will use CocoaPods, a dependency manager for Objective-C, which makes it easiest to keep the SDK up-to-date:

target "Guide" do
  pod 'ContentfulDeliveryAPI'

However, you are free to use Git submodules or [download a static framework][6] if that suits your workflow better.

Configuring the API client

The class CDAClient manages all requests to the API. For most apps, you will have a single Space which contains all your data. In this case, it is recommended to create a singleton category on top of CDAClient to make it simple to dispatch requests from any part of your app:

@implementation CDAClient (Guide)
  +(instancetype)sharedClient {
    static dispatch_once_t once;
    static CDAClient *sharedClient;
    dispatch_once(&once, ^ {
      sharedClient = [[self alloc] initWithSpaceKey:@"YourSpaceKey"
    return sharedClient;

For creating a client object, the Space key and a Content Delivery API access token are required.

Accessing data

Now that the client is available everywhere, you can fetch entries:

[[CDAClient sharedClient] fetchEntriesMatching:@{ @"content_type": @"3hEsRfcKgMGSaiocGQaqCo" }
                                       success:^(CDAResponse *response, CDAArray *array) {
                                           self.places = array.items;
                                       } failure:nil];

A CDAArray contains a list of CDAResource objects whose concrete type depends on the query. In this case, the *items* property will contain a list of CDAEntry objects.

Each CDAEntry has a fields property, containing the values for Fields defined in the content model. To decouple your app from Contentful, you can register custom subclasses for Content Types, like this:

[sharedClient registerClass:[BBUPlace class] forContentTypeWithIdentifier:@"3hEsRfcKgMGSaiocGQaqCo"];

The BBUPlace class defines properties like:

-(NSString *)name {
  return self.fields[@"name"];

so that you can deal with Entries like with any other value object.

In the guide app, the class also implements the *MKAnnotation* protocol, which enables directly showing Entries in a map view.

Simple views for your data

The initial view of the guide app is a list of all coffee places it knows about. For common tasks like this, the SDK brings some UI components which can be customized to your needs. In this case, we will create a subclass of CDAEntriesViewController, a UITableViewController optimized for showing a list of Entries matching a certain query.

The basic setup is done in your subclasse's init method:

-(id)init {
  self = [super initWithCellMapping:@{ @"textLabel.text": @"",
                                       @"detailTextLabel.text": @"fields.type" }];
  if (self) {
    self.client = [CDAClient sharedClient];
    self.query = @{ @"content_type": @"3hEsRfcKgMGSaiocGQaqCo" };
  return self;

The cell mapping is a dictionary for specifying which property of the UITableViewCell corresponds to properties in the content model. In addition to that, the shared client is specified as the client to use and the entries are limited to a certain Content Type. Setting the query property is optional, in that case all Entries will be shown.

If you want to show Resources in a UICollectionView, there is CDAResourcesCollectionViewController. It works similar to the Entries view controller:

self = [super initWithCollectionViewLayout:layout cellMapping:@{ @"imageURL": @"URL" }];
if (self) {
    self.client = [CDAClient sharedClient];
    self.resourceType = CDAResourceTypeAsset;

You need to specify a layout, just like in a normal UICollectionViewController and there is also the cell mapping again. For convenience, there is a ready made collection view cell class which fetches images from the URL in its imageURL property, so that is what we are going to use in this example. The resourceType property defines which type of Resource is going to be fetched, in this case Assets. A CDAAsset has a direct accessor for the URL which is used in the cell mapping here. Finally, the client needs to be specified, like in the previous example.

Presenting data your own way

Of course, it is also possible and often needed to write normal UIViewController subclasses and just pull in some data from Contentful. The class BBULocationViewController from the guide app does just that, utilising the BBUPlace class mentioned earlier. That way, it does not have specific knowledge about the Contentful SDK.

Two things to consider here:

Links might not be resolved, depending on your query. If that is the case, use the resolveWithSuccess:failure: method on any CDAResource. This should be done inside your custom class, look at the fetchPictureAssetsWithCompletionBlock: method from BBUPlace for an example.

Fields can include Markdown. There is another example app which shows how to use the Bypass library for converting Markdown into NSAttributedString which can be displayed in a UITextView since iOS 7. Depending on your use case and target platform, you might want to evaluate other options, for example converting to HTML.

With this, our walk through the coffee guide app is done. You should have everything you need to start building your own iOS apps with Contentful. Check out the SDK and start building.

For more information about managing content in native iOS, watchOS, tvOS and OS X apps, see our article: Selecting an iOS CMS.

[1]: [2]: [3]: [4]: [5]: [6]: [7]: [8]: [9]: [10]: [11]: [12]: [13]: [14]: [15]: [16]: [17]: [18]: [19]: [20]: [200]:

About the author

Don't miss the latest

Get updates in your inbox
A monthly newsletter to help you build better digital experiences with Contentful.
add-circle remove subtract-circle