Fat Fractal Tutorial for iOS: Getting Started

Learn how to make an iOS app with a back end like Twitter in this beginner Fat Fractal tutorial! By .

Leave a rating/review
Save for later
Share
You are currently viewing page 3 of 5 of this article. Click here to view the first page.

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?