Fat Fractal Tutorial for iOS: Getting Started

Gabriel Lim Gabriel Lim
Learn how to use the Fat Fractal back end as a service (BAAS)!

Learn how to use the Fat Fractal back end as a service (BAAS)!

Mobile backend services, also known as BaaS (Backend-as-a-Service), have become very popular these days because they save you a ton of time and money when it comes to developing an app that needs a remote database.

Tutorial Team member Antonio Martinez recently wrote an article about how to choose the best backend provider for your iOS app that covered many of the most popular options, like Parse, StackMob, and more.

In the time since Antonio wrote that article, there’s a new game in town! It’s called Fat Fractal, and we’re big fans.

Fat Fractal offers a number of advantages over other back-end providers, and in this tutorial we’re going to give you some hands-on experience with it so you can see if it’s right for you.

Keep reading to learn more about Fat Fractal, and how it stands out from other service providers like Parse!

Why Fat Fractal?

I have used Parse, Stack Mob, and recently a few months ago, Fat Fractal to write apps for my iOS consulting company. There were always something that didn’t feel quite right when using Parse or Stack Mob.

  1. Data modeling. Providers like Parse force you to use their own objects called PFObjects. This made me feel uncomfortable as I like to define my objects as subclasses of NSObject, instead of having extra overhead or lock-in in case I decide to change backend providers.
  2. Querying for data. Some extremely simple queries, if you are writing your own backend, turn into unimaginably complex API calls when using services like Parse. I remember writing an Instagram-like app for a client which had to make over 10 (!) separate API calls to the backend to just retrieve a profile page, when using Parse. This adds to alot of round trip requests and slow loading times.
  3. Server-side extensions. Way too much code that should be executed on the server, are instead being done on the iOS client. This is because the lack of control and access you have on the backend on services like Parse and Stack Mob.

So how does Fat Fractal stack up with regards to the rest of the BaaS providers? Let’s hear it from the founders of Fat Fractal themselves:

Compared to other BaaS, Fat Fractal is better thought through, and does not end up being a frustration at some point when you want to do something hard. The focus is on not limiting a developer in any way.

What we feel we do well:

  1. Datagraphs and relationships, including back references, which we have filed patents for. This is extremely powerful, and you can literally retrieve an object graph in a single query.
  2. Queries and the ability to walk through datagraphs to get what you want very efficiently.
  3. Permissions and security are way better thought through than anyone else.
  4. Support for native objects (NSObjects) that does not intrude on your client code, and support for binary data.
  5. The ability to develop your backend on localhost, test, debug and then deploy it to the cloud when you are satisfied.”

Also, Cory Wiles, a long-time iOS developer and BaaS enthusiast, has two blog posts about his experience with Fat Fractal which you can read here and here. Also, you can find his recent BaaS comparison reports – lots of extremely detailed information here, definitely worth checking out!

Here is a quote from Cory on why he loves Fat Fractal:

“Over the past 2 years I have used various BaaS services (Parse, Stackmob, Kinvey) with production apps and where I hand-rolled my own webservices using RDBMS, as well as NoSQL, which are not just ‘hello world’ tutorials. Each one has its niche in the market; but when making the decision of which service I would use for developing WhoNote, and any future applications, FatFractal is the clear choice.

I am able to keep clean, native objects easily, define a complex object-graph, implement proper server-client design with extensions, event handlers, scheduled tasks and last, but not least, have configurable implicit and explicit permissions while developing in an exact duplicate, local, development environment that I then push to the cloud. FatFractal is the next evolution of app development platforms.”

So with that, here is a tutorial for you to try out Fat Fractal for yourself, and see how it can help you reduce server-side complexities as an iOS developer!

Getting Started

In this tutorial, you will be building a social networking app similar to Twitter – but implemented 100% by yourself. :]

Your app will allow users to posts short messages like “tweets”, follow/unfollow other uses, and see “tweets” from users that they have followed.

Most of the heavy lifting and data querying will be done by the server backend, so you would need a robust BaaS service provider like Fat Fractal to do so.

So let’s create an account! Head over to Fat Fractal and click Login / Register:

Login

Fill in your email and the password you want, and follow the instructions there after to get your FatFractal account.

FatFractalRegistration

Check your email for a verification link to complete activation of your account. Click on the link and log in to your account.

ValidateEmailForFatFractal

You will be redirected to a welcome page, with a big button that allows you to Add a new Domain. Click that:

Add a Domain

In the form that appears, fill in the name of the domain you want. For this tutorial, I am using rwtweet as my domain name. You will have to use something else. The description is optional and you can fill in anything you want.

New Domain

Next, add an application to your domain by clicking on Add a new application:

Add a new application

Choose NoServer for Type, No Server Sandbox for Subscription, the domain you entered earlier, and then name the app the same as your domain. You can give it an optional description if you would like as well.

NewApp

Click Create, and you are done! You now have a fully working application and backend running in the cloud – though you can’t interact with it just yet ;)

Installing FatFractal Locally

Next, you will install FatFractal locally on your computer. For those of you who have experience with web development, you are probably familiar with developing and testing your web applications locally before deploying them to the cloud. Sadly, most BaaS do not support this feature, which means that you are always developing in production – which is dangerous.

Luckily, FatFractal supports local development, which you can then push to the cloud and ‘live’ your code when you are satisfied. This is one of the key strengths of FatFractal – the ability to build your backend locally, which is much faster, efficient and safer than compiling, deploying and tweaking over the internet. As their webpage states – “You are installing a fully featured FatFractal Engine on your desktop. This is not a crippleware version, not a simulation.” Check this link out for more information.

Head over to http://fatfractal.com/docs/getting-started/ and download the FatFractal Engine and Command-Line Tools (scroll down to the “Get down to business” section to find the links):

DownloadFatFractalEngine

Once the download is complete, unzip the file to a location of your choice, preferably your Home directory. You are now going to add the FatFractal_Runtime/bin directory to your path. This allows you to run command line instructions without referencing the full path. Open up Terminal, and type in nano ~/.bash_profile as such:

NanoBashProfileOne

Press Enter, and you should see your bash_profile, which may have other lines of code in it. Add the following to the bottom of your file (do not touch any of the other lines!): export PATH=/(your FatFractal installation directory)/FatFractal_Runtime/bin:$PATH

NanoBashProfileTwo

Save and exit by pressing Control-X and pressing Y and Enter when prompted if you want to save your changes.

Restart Terminal at this point so it picks up your new path changes.

Next, you are going to scaffold your application backend. Scaffolding an app creates a directory structure with essential files needed by the backend so that the application can be deployed to the engine. Create a new directory for your application and change to it inside Terminal:

> mkdir rwtweet
> cd rwtweet

Scaffold your application using the ffef command – but replace the bracketed entries with what you entered for your domain name and app name in FatFractal. For example, I used rwtweet for both.

> ffef newapp [YOUR DOMAIN NAME] [YOUR APP NAME]

Note: FatFractal requires Java JRE1.6 to run. If you don’t have it installed already, it will be installed automatically after you issue this command.

Fat Fractal will then generate a scaffolded application for you:

Scaffolding2

At this point, your application backend is ready to be deployed. Deployment delivers your scaffolded backend to a FatFractal Engine for execution in the cloud.

So let’s deploy your backend application to the cloud right now! Deploy your application with the ffef command:

> ffef deployFFFabric

You should be prompted for your email and password, you will have to answer Yes to the question “Would you like to validate your domain[rwtweet] and context[rwtweet] before deploying to the FatFractal Cloud?” and will see something like the following in your Terminal:

DeployedApplication

After your Terminal reads Done, head over to .fatfractal.com/ and you should see something like this:

Deploying to Fat Fractal

Congratulations – you have successfully deployed your backend to the cloud!

Now it’s time to set up your iOS client and write some Objective-C code.

Downloading the SDK and Starter Project

Before you can set up the iOS Client, you need to download the FatFractal iOS SDK. This will allow your application to easily interface with the FatFractal backend. Head over to http://fatfractal.com/prod/docs/getting-started/ and download the FatFractal iOS SDK.

DownloadingTheiOSSDK bordered

If you unzip the file you downloaded, you should get a folder named FFEF.framework. Remember where you unzipped this file – you will need it soon.

Next, download the starter project I prepared for you. This starter project has the user interface pre-created so you can focus on the Fat Fractal-related code in this tutorial.

Open the project in Xcode and build and run. The first thing you will see is a login screen, as well as two buttons that lead to a Sign up and Log in page:

The login screen

However, there is no backend or logic to handle this yet, you’ll create these functions shortly.

Before you proceed any further, have a look at the structure and flow of the app by opening MainStoryboard.storyboard.

FirstShotMainStoryboardView

The project starts from a root view controller called Tab Bar Controller. It has only one tab for now, the UINavigationController which houses the MainFeedViewController – a table view controller.

This MainFeedViewController will be responsible for showing all the tweets from your users. It will look something like the real Twitter iOS application – but not quite as colorful.

TwitterRealMainFeedViewController

The WelcomeViewController is the landing page for users who have not logged in or signed up yet. It is a modal view controller that is presented by the MainFeedViewController, hence it is not directly linked to any controllers in the storyboard. It is supposed to be similar to the Twitter landing view when you first download the app and launch it.

TwitterRealWelcomeViewController

The color here could also use a little work. :] But anyways, this WelcomeViewController will link to the SignupViewController and LoginViewController respectively for the user to authenticate themselves with the backend web service.

Ok, so now that you are oriented around the application, you can begin configuring your project to work with FatFractal!

Setting Up The iOS Client

Drag your entire FFEF.framework folder into your Framework folder in the project navigator menu of your Xcode project. When prompted, check Copy Items.. and Create Groups..:

DragFFEFframeworkToProject

When done, test that your Xcode project is able to build with the FFEF.framework linked in by building the project (Build or ⌘B). Everything should run without error. If so, this means that your app is integrated with the FatFractal SDK. You are now ready to work with the service!

The next logical step is to create some sample objects as a sanity check, and to finally see your backend in action!

Creating Sample Objects

The cool thing about FatFractal is that it uses native Objective-C classes for its backend data modeling. This is your object definition. The FatFractal platform does not create dependencies in your code by requiring you to use their own proprietary object classes like most other BaaS. (PFObject anyone?)

This prevents vendor lock-in, which means that you do not have to rewrite your entire application – models, controllers and all if you ever decide to migrate backend service providers. Pretty thoughtful of the folks at FatFractal!

Lets create your first test object – a TestZombie class that you will solely use for testing purposes.

Choose File > New > New File or ⌘N to bring up the Template Chooser for the new class file. You will use the standard Objective-C class template. Click Next.

NewTestZombieClassTemplate

Enter the name of the Objective-C class, TestZombie, as a subclass of plain old NSObject. Then click Next and then Create and Xcode will add TestZombie.h and TestZombie.m files in your project.

NewTestZombieClassNSObject

Modify TestZombie.h to include the properties for the class as such:

#import <Foundation/Foundation.h>
 
@interface TestZombie : NSObject
 
@property (strong, nonatomic) NSString *name;
@property (strong, nonatomic) NSString *gender;
@property (strong, nonatomic) NSString *mortalEnemy;
 
@end

Here you create three properties – one for the zombie’s name, one for its gender, and one for its mortal enemy – like shotguns!

Because in Xcode 4.5, properties are automatically synthesized for you, you can leave the TestZombie.m file alone.

That’s it for the test object model – let’s create an instance of the main class you will use to work with FatFractal.

Adding The FatFractal Instance

To work with Fat Fractal, you need to create an instance of a class named FatFractal that comes in the FFEF framework you added earlier.

You will instantiate the FatFractal as a singleton in the AppDelegate class. This is to ensure there is only one instance of FatFractal living in your application at any one time – any reference to it will be grabbed from AppDelegate.

You first have to import the header file from the FFEF framework. Because you will be using the FatFractal class in many places – let’s import it in your Tweetie App-Prefix.pch file which will automatically import in this framework for all your files.

Open Supporting Files\App-Prefix.pch and add this file to import the FFEF header:

#import <FFEF/FatFractal.h>

Then switch over to AppDelegate.m, and add the following below your import statements:

#import "TestZombie.h"
 
static NSString *baseUrl = @"http://<YOUR APP DOMAIN>.fatfractal.com/<YOUR APP NAME>";
static NSString *sslUrl = @"https://<YOUR APP DOMAIN>.fatfractal.com/<YOUR APP NAME>"; 
static FatFractal *_ff;

Remember to replace and with your proper identifiers, as such: http://rwtweet.fatfractal.com/rwtweet

Then add the a static method to retrieve the Fat Fractal singleton inside your @implementation:

+ (FatFractal *)ff {
  return _ff;
}

Still inside AppDelegate.m, add the following at the top of your application:didFinishLaunchingWithOptions: method:

// Initialize the FatFractal instance that your application will use
_ff = [[FatFractal alloc] initWithBaseUrl:baseUrl sslUrl:sslUrl];
// Set debug mode to on for this tutorial
_ff.debug = YES;
// The following is testing code. Remove when you are done testing
NSError *error;
[_ff loginWithUserName:@"test_user" andPassword:@"Test_user123!" error:&error];
if (!error) {
    TestZombie *testObject = [[TestZombie alloc] init];
    testObject.name = @"Shane the Zombie";
    testObject.mortalEnemy = @"Rick Grimes";
    testObject.gender = @"male, hopelessly male.";
    [_ff createObj:testObject atUrl:@"/TestZombie" error:&error];
}

Here you’ve created a new instance of the FatFractal class, passing in the URL for the app you created earlier. You also turn debug mode on so you can see some verbose log messages.

Next, you added some test code to make sure Fat Fractal is working. Here you log in with a fake test user, create an instance of a zombie, and add it to your back end database. You’ll learn more about how all this works later on.

Finally, add the declaration for your ff method to AppDelegate.h:

+ (FatFractal *)ff;

Once done, build and run. If all succeeds, you should see a mess of debug statements in your console log, but the most important statement you will see is highlighted:

FirstPostToServerBuildSucceeds

It reads, “statusMessage : Created new resource /ff/resources/TestZombie/…”. This is a HTTP response from the web server to let you know that the POST request to create an object was successful, along with other meta-data that you will analyse in Part Two.

Let’s not take your console log’s word for it, and do a manual check on the web service to see that your object is really created. Head over to your web service’s URL at http://.fatfractal.com//ff/resources/TestZombie to check it out. My URL is http://rwtweet.fatfractal.com/rwtweet/ff/resources/TestZombie. You should see something similar to the following:

TestZombie

What you see is the JSON data containing the details of the TestZombie object you just created. Walking Dead fans will approve!

You realize that you were able to create your own object classes without having to use third party object models. Simply by passing in your native Objective-C data structure, it creates your object’s data model on the backend for you.

Sweet! Now comment out the test code you just added, since you won’t be needing that anymore:

/*
NSError *error;
[_ff loginWithUserName:@"test_user" andPassword:@"Test_user123!" error:&error];
if (!error) {
    TestZombie *testObject = [[TestZombie alloc] init];
    testObject.name = @"Shane the Zombie";
    testObject.mortalEnemy = @"Rick Grimes";
    testObject.gender = @"male, hopelessly male.";
    [_ff createObj:testObject atUrl:@"/TestZombie" error:&error];
}
*/

About FFUser

On the FatFractal platform, there is a special object called FFUser that represents users. It behaves exactly like any other object, except for some predetermined properties.

By default, Fat Fractal is set to auto-register a user upon first log in. This means when a user tries to log in, if the username does not exist already Fat Fractal automatically creates a new an FFUser object with two properties: userName and password.

You saw an example of this earlier – in the test code, it logged a test user in with a certain username and password even though you never explicitly created that user. Behind the scenes, Fat Fractal automatically created a FFUser object for you.

By default, a user has read and write permissions on every object they create. Also by default, every registered user has read permissions on every other users’ objects, but not write permissions. Unregistered users may not create objects on the backend, but may read anything with public read permissions.

Most of this default behavior for FatFractal serves your needs fine for now, except for one. You don’t actually want Fat Fractal to auto-register users, like you saw in the test code. Instead, you want them to go through your sign up process first.

Inside your rwtweet directory (the one you created earlier with the Fat Fractal scaffolding), search for and open ff-config/application.ffdl. For those of you who are using TextMate, you can just cd into tweetie directory and type

> mate .

When you open application.ffdl, you should see multiple lines of configuration code. You want to edit the AllowAutoRegistration value:

FreshCopyofAppFFDL

Change the value from true to false, like this:

EditedToFalseApplicationFFDL

Save the file. Go to Terminal and deploy your new settings to your application in the cloud. Type in your Terminal:

> ffef deployFFFabric

If prompted if you would like to validate your domain again, key in No (N).

Building The Authentication System

Next let’s build your authentication system.

Open SignupViewController.m, and add the following code to signupButtonPressed: right after the “TODO” comment:

// Step 1
FFUser *newUser = [[FFUser alloc] initWithFF:[FatFractal main]];
newUser.firstName = fullname;
newUser.userName = username;
newUser.email = email;
 
// Step 2
[[FatFractal main] registerUser:newUser password:password onComplete:^(NSError *theErr, id theObj, NSHTTPURLResponse *theResponse) {
 
    // Step 3
    if (theErr) {
        [MBProgressHUD hideHUDForView:self.view animated:YES];
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error" message:[theErr localizedDescription] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
        [alert show];
        return;
    } else {
        // Step 4
        if (theObj) {
            // App is now in signed in state.
 
            // Step 5
            [self saveUserCredentialsInKeychain];
 
            [MBProgressHUD hideHUDForView:self.view animated:YES];
 
            // Step 6
            [self dismissViewControllerAnimated:YES completion:^{
                [self handleSuccessfulSignup];
            }];
        }
    }
}];

The above code registers a new user. Let’s go over it step by step:

  1. Here you create a new FFUser instance using the FatFractal singleton. You then assign the properties of the FFUser as the user input in the textfields
  2. You then call the registerUser:password:onComplete: method on your FatFractal singleton. This method will attempt to sign up a user, and provide a callback when the backend server replies to you.
  3. If there is an error, you hide the progress view and display an alert.
  4. If there is no error, you double check that the server returned you an object, which is your FFUser object actually. Your app is now in a signed in state.
  5. You then save the user’s credentials in your keychain so you can automatically log the user in from hence forth.
  6. You then dismiss the modal view controller, and send your delegate a message – that the sign up was successful.

Next inside AppDelegate.h, declare a new class method:

+ (BOOL)checkForAuthentication;

Inside AppDelegate.m, implement this method:

+ (BOOL)checkForAuthentication {
    if ([_ff loggedIn] || ([_keychainItem objectForKey:(__bridge id)(kSecAttrAccount)] != nil && ![[_keychainItem objectForKey:(__bridge id)(kSecAttrAccount)] isEqual:@""])){
        NSLog(@"checkForAuthentication: FFUser logged in.");
        return YES;
    } else {
        NSLog(@"checkForAuthentication: No user logged in.");
        return NO;
    }
}

Inside MainFeedViewController.m, import AppDelegate.h:

#import "AppDelegate.h"

Then inside checkForAuthentication replace the line if (false) { with the following:

if ([AppDelegate checkForAuthentication]) {

This checks to see if the user is logged in, and if not presents the WelcomeViewController.

And with this, you can now sign up new users for your application! >Build and run and try to sign up a new user. You should see the modal Welcome View Controller dismiss itself and show you your MainFeedViewController table view if successful.

MainFeedViewControllerAfterRunningSignup

Not bad for just a few lines of code, eh?

Building The Authentication System Part II

Let’s complete the rest of the authentication system while you are at it.

Open AppDelegate.m, and let’s make the application automatically log in the user if there are user credentials in the keychain.

Inside application:didFinishLaunchingWithOptions:, add the following code after the “Login with FatFractal by initiating connection with the server” comment:

// Step 1
[_ff loginWithUserName:username andPassword:password onComplete:^(NSError *theErr, id theObj, NSHTTPURLResponse *theResponse) {
 
    // Step 2
    if (theErr) {
        NSLog(@"Error trying to log in from AppDelegate: %@", [theErr localizedDescription]);
        // Probably keychain item is corrupted, reset the keychain and force user to sign up/ login again.
        // Better error handling can be done in a production application.
        [_keychainItem resetKeychainItem];
        return ;
    }
 
    // Step 3
    if (theObj) {
        NSLog(@"Login from AppDelegate using keychain successful!");
        [self userSuccessfullyAuthenticated];
    }
}];

In the code above, you login an existing user in the keychain by:

  1. Calling the loginWithUserName:AndPassword:onComplete method on your FatFractal instance, which will return with a response from the server.
  2. If there is an error, your keychain item is probably corrupted. Thus, you will clear it, and force the user to sign up and log in again when he next launches the application. In a production application, more robust error handling can be done.
  3. If there is no error, and the server returns you an FFUser object, you will send a message to the MainFeedViewController to inform it that user is successfully authenticated. This is so that you can know when to download the tweets and user information, as well as refresh the table view in the MainFeedViewController.

Build and run your application. If all goes well, in the log you should see the FFUser object being returned by the server and your log message that login from the app delegate using keychain was successful:

AppDelegateLoginAutomaticallyFirst

The Login View Controller

Registration works great, but the Login View Controller still doesn’t work, so let’s add the code for that next.

Open LoginViewController.m and add the following code to loginUserWithUsername:andPassword: after the “TODO” comment:

#pragma mark - Helper Methods
// Login with FatFractal, save to keychain and handleSuccessfulLogin if successful
// Step 1
[[FatFractal main] loginWithUserName:usernameText andPassword:passwordText onComplete:^(NSError *theErr, id theObj, NSHTTPURLResponse *theResponse) {
 
    // Step 2
    if (theErr) {
        NSLog(@"Error logging in from LoginViewController: %@", [theErr localizedDescription]);
        [MBProgressHUD hideHUDForView:self.view animated:YES];
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error" message:@"Your username and password could not be authenticated. Double check that you entered them correctly and try again." delegate:self cancelButtonTitle:@"OK" otherButtonTitles: nil];
        [alert show];
    } else {
 
        // Step 3
        if (theObj) {
            // App is now in signed in state.
            [self saveUserCredentialsInKeychain];
 
            [MBProgressHUD hideHUDForView:self.view animated:YES];
 
            [self dismissViewControllerAnimated:YES completion:^{
                // Upon successful dismiss, handle login.
                [self handleSuccessfulLogin];
            }];
 
        }
    }
}];

In the code above, you login an user to your Fat Fractal backend by:

  1. Calling the loginWithUserName:AndPassword:onComplete method on your FatFractal instance, which will return with a response from the server.
  2. Handle the error, if any. Notice that you do not display the localized error, you will explain why in a short while.
  3. Check that the server actually returned you the FFUser object, save your credentials in the keychain and dismiss the modal view.

Now, why don’t you show the localized error message?

The reason is that the error message will reveal that the user is either using an incorrect password or user name that does not exist. This is bad in terms of security as you don’t want to make it easy for people to guess user names or passwords. Thus, you give a generic message that makes it hard to guess if the user name exists or the password is wrong. You can see it in the logs below:

IncorrectPasswordSecurityIssueOne
IncorrectPasswordSecurityIssueTwo

For now, you will not be using the Login View Controller, as you are automatically logged in when you sign up, and there is no log out function as of yet.

You will come to that in a while.

Adding Your First Tweet

What Twitter clone would you have if the user can’t even post his or her tweet?

Let’s create the Micropost object that will hold your tweets.

Choose File > New > New File or ⌘N to bring up the Template Chooser for the new class file. You will use the standard Objective-C class template. Click Next.

Enter the name of the Objective-C class as Micropost, a subclass of NSObject.

Modify Micropost.h as follows:

#import <Foundation/Foundation.h>
 
@interface Micropost : NSObject
 
@property (strong, nonatomic) NSString *content;
@property (strong, nonatomic) FFUser *user;
 
@end

Next, let’s create your AddTweetViewController.

Choose File > New > New File or ⌘N to bring up the Template Chooser for the new class file. We will use the standard Objective-C class template. Click Next.

Enter the name of the Objective-C class as AddTweetViewController, a subclass of UIViewController.

CreatingAddTweetViewControllerOne

Next, let’s create the user interface for your AddTweetViewController in your storyboard. Drag a new View Controller object into your storyboard, select it, and change it’s class to AddTweetViewController under it’s Identity Inspector.

ChangingViewControllerToAddTweetVC

Next, drag a UITextView, UINavigationBar and two UIBarButtonItems and set up your user interface as such:

SettingUpTheAddTweetUI

Connect your text view to an outlet called tweetTextView, the cancel button to an action called cancelButtonPressed:, and the tweet button to an action called tweetButtonPressed::

ConnectingUpAddTweetViewController

Next open AddTweetViewController.m and import the Micropost header at the top of the file:

#import "Micropost.h"

Make the text field the first responder when the view loads and clear the text by adding this to the viewDidLoad method:

- (void)viewDidLoad
{
    [super viewDidLoad];
    [_tweetTextView becomeFirstResponder];
    [_tweetTextView setText:@""];
}

Then in edit the cancelButtonPressed: method to simply dismiss the view controller:

- (IBAction)cancelButtonPressed:(id)sender {
    [self dismissViewControllerAnimated:YES completion:nil];
}

And replace tweetButtonPressed: with the following:

- (IBAction)tweetButtonPressed:(id)sender {
 
    // Check if logged in user exists (logged in)
    if ([[FatFractal main] loggedInUser]) {
        Micropost *myPost = [[Micropost alloc] init];
        myPost.content = _tweetTextView.text;
        myPost.user = [[FatFractal main] loggedInUser];
        [[FatFractal main] createObj:myPost atUri:@"/Micropost" onComplete:^(NSError *theErr, id theObj, NSHTTPURLResponse *theResponse) {
            if (theErr) {
                NSLog(@"Error, can't post at this time.");
            }
 
            if (theObj) {
                NSLog(@"Success! Micropost created: %@", theObj);
                [self dismissViewControllerAnimated:YES completion:nil];
            }
        } onOffline:^(NSError *theErr, id theObj, NSHTTPURLResponse *theResponse) {
            FFQueuedOperation *operation = (FFQueuedOperation *)theObj;
        }];
    }
}

You first check if the user is logged in, and create a new Micropost object with the text and currently logged in users as the properties.

You then call the createObj: method on your FatFractal singleton to create and post the object to your web service. This should be familiar to you by now.

The interesting thing here is the onOffline: block.

Fat Fractal supports offline queuing for most operations, in case the client is offline. The Fat Fractal SDK will try to complete any queued operations every 1 second while the client is online, and every 10 seconds while your client is offline.

The queued operations are saved to the iOS device local storage, so they survive app restarts, termination etc. This is very useful when designing an app like Twitter, which if your user tweets a post while in an area without network connectivity, the app will ‘hold’ or queue the post for you, and post it to the server when the user has connectivity again.

Allright! The last step is to display the new Add Tweet View Controller modally from the Main Feed View Controller.

Open MainFeedViewController.m and import the file:

#import "AddTweetViewController.h"

Then open MainStoryboard.storyboard and drag a UIBarButtonItem from your Object library to the navigation bar of your Main Feed View Controller like this:

DraggingUIBarButtonToMainVC

Change the Identifier of the UIBarButtonItem under the Attributes Inspector to Add.

ChangingTheUIBarButtonItemAttribute

Next, connect the UIBarButtonItem you added to the AddTweetViewController through a modal segue by Ctrl-Dragging from the button to the AddTweetViewController:

ConnectingModalSegueFromUIBtnToAddTweet

And select Modal Segue when the pop up appears:

ModalSegueSelectionUIBarBtn

Allright! Run the app now try adding a tweet.

To do this, click on the + Bar Button, and you should see the AddTweetViewController’s modal view appear. Type in what ever you like, and hit the Tweet button:

RunYourFirstTweet

You should see something like the following in your logs, signifying that your post was successful!

FirstTweetSuccessPartOne

FirstTweetSuccessPartTwo

If you go to your Fat Fractal domain, using your web browser, at https://[YOUR DOMAIN].fatfractal.com/[YOUR APP NAME]/ff/resources/Micropost, you will see that your object has been created in your backend, along with other JSON data:

FirstTweetSuccessPartThreeBackedn

Our table view is still empty though.. So let’s retrieve this data and format it to your table view.

Retrieving And Displaying The First Tweet

Open MainFeedViewController.m, import your Micropost.h file:

#import "Micropost.h"

Next, you need an array to hold all the posts that you download from the web service, and a property to keep track of your current user. Change the @interface directive inside MainFeedViewController.m to look like this:

@interface MainFeedViewController ()
@property (strong, nonatomic) NSMutableArray *postsArray;
@property (strong, nonatomic) FFUser *currentUser;
@end

Then add this new method:

- (void)refresh {
    if ([[FatFractal main] loggedInUser]) {
        self.currentUser = [[FatFractal main] loggedInUser];
        [self refreshTableAndLoadData];
    }
}

Basically, what you are doing here is to check if there is a logged in user. If there is, you will assign the currentUser to the currently logged in user, as well as refresh the table with the new data from your backend.

Call this method from both viewDidLoad and userIsAuthenticatedFromAppDelegateOnLaunch:

[self refresh];

Let’s implement the refreshTableAndLoadData method now. Add the method below your viewDidLoad method:

-(void)refreshTableAndLoadData {
 
    // Clean the array
    if (_postsArray) {
        [_postsArray removeAllObjects];
        _postsArray = nil;
    }
 
    // (Re) Create the array
    _postsArray = [NSMutableArray array];
 
    [[FatFractal main] getArrayFromUri:@"/Micropost" onComplete:^(NSError *theErr, id theObj, 	 	NSHTTPURLResponse *theResponse) {
 
		if (theObj) {
            _postsArray = (NSMutableArray *)theObj;
 
            [self.tableView reloadData];
        }
    }];
}

You will check if the postsArray instance variable exists. If so, you will remove all objects from it and set it to nil. You then create the postsArray again.

To retrieve data from your FatFractal backend, you just need to call getArrayFromUri: on your singleton, and pass in the URI endpoint for the data you want to retrieve. In this case, it is /Micropost. This will retrieve all the objects from https://.fatfractal.com//ff/resources/Micropost for us.

Remember to call the refreshTableAndLoadData method in your callback too, so that this method will be invoked when you log in from the App Delegate.

#pragma mark - Public Methods
-(void)userIsAuthenticatedFromAppDelegateOnLaunch {
    [self refreshTableAndLoadData];
}

Lastly, you need to set up your table view to be able to show the data. Change your table view data source methods to look like this:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    // Return the number of sections.
    return 1;
}
 
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // Return the number of rows in the section.
    return [_postsArray count];
}

And add this code inside your tableView:cellForRowAtIndexPath: after the “To Do: Display Microposts from posts array” comment:

if ([_postsArray count] > 0) {
    Micropost *micropost = [_postsArray objectAtIndex:indexPath.row];
    NSString *text = micropost.content;
    CGSize constraint = CGSizeMake(TEXT_WIDTH, 20000.0f);
    CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:[UIFont systemFontSize]] 						constrainedToSize:constraint lineBreakMode:NSLineBreakByWordWrapping];
    if (!micropostLabel) {
        micropostLabel = (UILabel *)[cell viewWithTag:1];
    }
    [micropostLabel setText:text];
    [micropostLabel setFrame:CGRectMake(TEXTOFFSET_X, TEXTOFFSET_Y, TEXT_WIDTH, MAX(size.height + 										5, 60.0f))];
 
    if (!fullnameLabel) {
        fullnameLabel = (UILabel *)[cell viewWithTag:3];
    }
    [fullnameLabel setText:micropost.user.firstName];
 
    if (!profileImageView) {
        profileImageView = (UIImageView *)[cell viewWithTag:2];
    }
    profileImageView.frame = CGRectMake(CELL_CONTENT_MARGIN, (MAX(size.height + 35, 60.0f) - 								IMAGE_SIDE)/ 2, IMAGE_SIDE, IMAGE_SIDE);
 
    [micropostLabel sizeToFit];
}

Allright – it’s to see the fruits of your labour! Build and run the app, and you should see the tweet that you posted earlier appear:

FirstTweetAppearingInTable

Where To Go From Here?

Here is the complete example project from the above Fat Fractal tutorial.

In this part, you learnt how to set up the Fat Fractal backend, use the Fat Fractal iOS SDK, how to build your own authentication system, post data to the backend, and retrieve this data from the backend.

But there’s a lot more to learn with Fat Fractal! I could show you how to extend this app even further to allow users to follow each other, upload images, and more – demonstrating some neat functionality about Fat Fractal along the way.

If you would like to see more about Fat Fractal, please let me know! Otherwise, if you have any questions or comments, please join the forum discussion below.

Gabriel Lim
Gabriel Lim

Gabriel is the co-founder of Getting Real Software where he does iOS and backend development from Singapore. He specialises in helping businesses earn more money and streamline their processes using mobile technology.

He also runs App Ninja, a resource for mobile app developers which aims to help fellow coders with app templates, tutorials and blog posts on mobile app development. You can reach him to have a chat at Twitter, his website, or email.

User Comments

13 Comments

  • Errata:
    This line in the tutorial:
    > ffef newapp [YOUR DOMAIN NAME] [YOUR APP NAME]
    Should have the parameters reversed. ie.,
    > ffef newapp [YOUR APP NAME] [YOUR DOMAIN NAME]
    bitfool
  • Incomplete tutorial: needs completion of the
    -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
    method in order to show the tweets (or comment it out, and tweets show but without proper row heights).

    Even then, there seems to be missing tutorial parts... tweet list should update after each new tweet is tweeted, but doesn't until app is stopped and restarted :-(

    Overall, a nice intro to FatFractal, thanks for that.
    bitfool
  • Awesome tutorial! :D I hope you make a part two with additional features! :D
    pjvea
  • bitfool wrote:Incomplete tutorial: needs completion of the
    -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
    method in order to show the tweets (or comment it out, and tweets show but without proper row heights).

    It's in the .zip file with the complete example project - works just fine :roll: Only the tutorial text needs to be updated ;)
    akonakov
  • akonakov wrote:
    bitfool wrote:Incomplete tutorial: needs completion of the
    -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
    method in order to show the tweets (or comment it out, and tweets show but without proper row heights).

    It's in the .zip file with the complete example project - works just fine :roll: Only the tutorial text needs to be updated ;)


    Thanks, I figured as much, but I hadn't downloaded that (felt like cheating) cause I wanted to work through the whole tut to get a better feel for FatFractal and how to use it.
    bitfool
  • Hey guys, thanks for the comments! I am sorry for the errata, and I'm working on fixing them in the tutorial. Anyways, akonakov is right, the source code is fully functional so you can refer to that in the meantime. Thanks for pointing out the errors though..

    Do let me know what you would like to see or explore further in Part II as I am working on that now. It will incorporate a following/unfollowing system, favouriting posts and commenting - among other features. Fat Fractal is a really powerful BaaS and we have only scratched the surface in this tutorial.

    Cheers,
    Gabriel
    Gabriel Limsg_gabriel
  • Fat Fractal needs JDK, not only JRE, just for clarification.
    Deny
  • Hello! i really liked this tutorial. it involved more depth of programming and messing with the terminal and path.
    Can you please make a follow-up, extending the app with more features? i will try to work on it by myself but would really love if you could make this guide incase i will need assistance :)
    Lior
  • Brilliant!

    I changed the code a bit to use a separate nib file for the "MicroPostCell" so I didn't have to configure it the way you have done but apart form that it was excellent!

    I'd love to learn more about FatFractal. Especially, is there a way to configure scripts on FatFractal itself?

    For me though, anything about it is excellent. I'm an iPhone dev with not really any back end experience so this is excellent.
    Fogmeister
  • About a million times better than the tutorials listed on the ff site! Thanks so much for this!
    Looking forward to seeing the next step (following etc!!)

    In MainFeedViewController.m just changed the viewDidLoad to incorporate a timer to check for tweets, is this about the best way to do it? Seems to work well for now...

    - (void)viewDidLoad
    {
    [super viewDidLoad];

    self.title = @"Tweetie";
    [self refresh];

    [NSTimer scheduledTimerWithTimeInterval:2.0
    target:self
    selector:@selector(updateTimer)
    userInfo:nil
    repeats:YES];
    }

    - (void)updateTimer {
    [self refresh];
    NSLog(@"updated");
    }

    Also wanted to ask about the potential of local notifications and tones for incoming messages? - will this be in part 2? :)
    newdeveloper
  • Looking forward to trying this tutorial. I did some work with parse as it was recommend in another RW post. It was really easy to use and great tutorials on how to use. I cannot see FF being better... i'll report back following completing this tutorial.
    mazza
  • Very good tutorial! Thank you!

    One suggestion: add [self refresh]; to the viewDidAppear method in MainFeedViewController.m so that the table view could refresh each time after the AddTweetView dismisses itself.
    yz3076
  • I was trying to accomplish this tutorial yesterday. When I got to the part before displaying the saved data in a table view, the app crashes and I get this message, '[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key tweetButtonPressed.' Does anyone have an idea what is causing this?
    golfguy18990

Other Items of Interest

Ray's Monthly Newsletter

Sign up to receive a monthly newsletter with my favorite dev links, and receive a free epic-length tutorial as a bonus!

Advertise with Us!

Hang Out With Us!

Every month, we have a free live Tech Talk - come hang out with us!


Coming up in September: iOS 8 App Extensions!

Sign Up - September

RWDevCon Conference?

We are considering having an official raywenderlich.com conference called RWDevCon in DC in early 2015.

The conference would be focused on high quality Swift/iOS 8 technical content, and connecting as a community.

Would this be something you'd be interested in?

    Loading ... Loading ...

Our Books

Our Team

Tutorial Team

... 49 total!

Update Team

Editorial Team

... 23 total!

Code Team

  • Orta Therox

... 3 total!

Translation Team

  • Heejun Han

... 33 total!

Subject Matter Experts

  • Richard Casey

... 4 total!