A JBoss Project
Red Hat

Getting Started with AeroGear and Xcode

This guide will help you to setup your development environment for AeroGear, and then build a simple application to verify the installation. The guide assumes that you have XCode IDE installed in your machine. If not, you can download it from the Apple developer web site here. Let’s get started.

Step 1: Create a new Xcode Project

Fire up Xcode and when presented with the welcome screen, choose "Create a new Xcode Project"

Welcome screen

On the next screen, choose "Empty Application"

New Project

Enter "AeroGearExample" in the Product Name field and your initials as the Class Prefix. In this example I used "AG". For the device family I used iPhone. Leave the default options checked.

Details

Xcode creates our project and we are presented with the default project screen.

Main Project Screen

Now that our project is created, its time to install required dependencies.

Step 2: Install Dependencies

Generally, there are two approaches to install dependencies.

The first approach (and the preferred one) is to use CocoaPods dependency manager. If you haven’t used it so far in your iOS projects, please take the time to familiarize yourself. It will make your life much easier when dealing with dependencies (and upgrades!). Have a look at the web site for installation details.

The second approach, is to manually add the dependencies to the project. Both approaches are discussed in this guide, so peak the approach you are most familiar with.

Approach 1: using CocoaPods

In the "Podfile", add the following lines:

xcodeproj 'AeroGearExample.xcodeproj'

pod 'AeroGear'

And then:

pod install

to install the dependencies.

NOTE: Don’t forget to open the Xcode workspace file instead of the project file after this step.

Approach 2: using manual Process

We need to download both AFNetworking and the AeroGear libraries from their respective sources.

Extract the zip archives and when finished, time to add them to our project.

First, we add AFNetworking. Click "File→Add files to AeroGearExample". In the dialog sheet that pops up, navigate to where AFNetworking code was extracted and select the AFNetworking folder

AFNetworking

Make sure that "Copy items into destination group’s folder" and "Create Groups for any added folders" is checked.

Now time to add AeroGear library. Click again "File→Add files to AeroGearExample". In the dialog sheet that pops up, navigate to where AeroGear code was extracted and select the "AeroGear" folder.

AeroGear

Again, make sure that "Copy items into destination group’s folder" and "Create Groups for any added folders" is checked.

Step 3: Verify installation

Now that our dependencies are set up, it’s time to verify our installation. For this, we are going to build a simple application that will fetch remote data from our testbed testbed server deployed on OpenShift. The data represent a list of developer information (image, name, twitter) that will be displayed on a standard UITableView component. Upon clicking a developer on the list, his twitter page will be opened using the system’s default browser. Let’s start.

  • 1: Create your controller

Create a new objective-c file, choose the name "AGViewController" and make it extend "UITableViewController".

  • 2: Link view and Navigation Controller

Click on the "AGAppDelegate.h" on the Project Navigator. We need to add a property for a UINavigationController, which will be used to embed our table view in it [1].

#import <UIKit/UIKit.h>

@interface AGAppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;
@property(strong, nonatomic)  UINavigationController *controller;  [1]

@end

Now, click on the "AGAppDelegate.m" on the Project Navigator. At the top of the file, add an import statement for the AGViewController class [1] we created earlier. Then, on the didFinishLaunchingWithOptions method add line [2] and [3] to initialize the Navigation Controller and our AGViewController class.

#import "AGViewController.h"  [1]
...

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.
    self.window.backgroundColor = [UIColor whiteColor];
    self.controller = [[UINavigationController alloc]     // [2]
                       initWithRootViewController:[[AGViewController alloc] initWithStyle:UITableViewStylePlain]];
    self.window.rootViewController = self.controller;     // [3]

    [self.window makeKeyAndVisible];
    return YES;
}
  • 3: Retrieve information

Now, click on the "AGViewController.m" on the Project Navigator. At the top of the file, add an import statement for the "AeroGear" library [1]. Then add an instance variable that will hold the data [2] returned from the server.

#import "AGViewController.h"
#import <AeroGear/AeroGear.h>                                           // [1]

@interface AGViewController ()
@end

@implementation AGViewController {
    NSArray *_data;                                                    // [2]
}

- (void)viewDidLoad {
    [super viewDidLoad];

    NSURL* projectsURL = [NSURL URLWithString:@"http://igtests-cvasilak.rhcloud.com/rest"];

    // create the server 'Pipeline'
    AGPipeline *server = [AGPipeline pipelineWithBaseURL:projectsURL];             // [3]

    // create the 'Pipe' that will point to the remote '/developer/' endpoint
    id<AGPipe> developerPipe = [server pipe:^(id<AGPipeConfig> config) {          // [4]
        [config setName:@"/team/developers"];
    }];

    // read from the 'Pipe'
    [developerPipe read:^(id responseObject) {      // [5]
        // hold the response
        _data = responseObject;     // [6]

        // refresh table view with the data returned
        [self.tableView reloadData];      // [7]

    } failure:^(NSError *error) {
        NSLog(@"An error has occured during pipe read! \n%@", error);
    }];


}
// the rest of your file ...

Central to AeroGear is the concept of Pipeline and Pipe. The former represents a collection of server connections and the latter the connection itself. In [3] we initialize our Pipeline object with the base URL of the remote application and then we call it’s pipe method [4] passing a configuration object that sets the name of the remote endpoint (in our case "/team/developers").

We then perform a read request [5] on the Pipe to fetch the data from the remote endpoint, passing a success and failure block. If the fetch was successful, we assign the returned result to our data object [6]. Finally, we ask the tableview to reload itself to display the data [7].

  • 4: Refresh Table View with data

Time to fill the empty table data source methods that Xcode created automatically for us when we created the class, with code that renders the fetched data.

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [_data count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if (cell == nil) {
        cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
    }

    // extract the developer
    NSDictionary *developer = [_data objectAtIndex:indexPath.row];  //  [1]

    // fill cell data   // [2]
    cell.textLabel.text = [developer objectForKey:@"name"];
    cell.detailTextLabel.text = [developer objectForKey:@"twitter"];
    cell.tag = indexPath.row;

    // fetch the twitter image asynchronous not to block UI
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul), ^{    // [3]
        NSData *imageData = [NSData dataWithContentsOfURL:
                             [NSURL URLWithString:[developer objectForKey:@"photoURL"]]];

        dispatch_async(dispatch_get_main_queue(), ^{
            if (cell.tag == indexPath.row) {   // [4]
                cell.imageView.image = [UIImage imageWithData:imageData];   // [5]
                [cell setNeedsLayout];
            }
        });
    });

    return cell;
}

In [1] we extract the developer object that is about to be rendered, from the list retrieved earlier during the initial Pipe read. We then use it to fill the cell data with developer information [2]. Since we don’t want to block the UI when the twitter image is fetched, we dispatch it asynchronously [3] with the power of GCD. When the image is finally fetched, we set it on the cell [5].

NOTE Since iOS table view component recycles cells in order to save memory (e.g. for large data sets), we need to ensure not to overwrite a recycled cell with an old image. The trick we use here is to assign a tag on the cell with the row index and we verify in [4] when we are about to display it.

  • 5: Open Twitter developer page

What is left now is to add functionality where when a cell is clicked the application open’s the system browser and redirects to the developer’s twitter page. Add the following method:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    // extract the developer
    NSDictionary *developer = [_data objectAtIndex:indexPath.row];  // [1]

    // format twitter url
    NSURL *url = [NSURL URLWithString:
                  [NSString stringWithFormat:@"http://twitter.com/%@", [developer objectForKey:@"twitter"]]];   // [2]

    // open twitter page
    [[UIApplication sharedApplication] openURL:url];  // [3]

    [tableView deselectRowAtIndexPath:indexPath animated:YES];
}

The didSelectRowAtIndexPath delegate is called when the user clicks a cell on the table. In [1] we extract the developer object as we did previously from the cell the user clicked. We then setup an NSURL object [2] that points to the developers twitter page and we ask the system to open it the browser [3].

  • 6: Run it!

Ok we are now ready to run the project. Select "Product→Run" and if all goes well you will be presented with the following screen.

Emulator

Success! Your first iOS application built with AeroGear!

You can download the source code of this project from github. For more complete example applications that utilize different parts of the AeroGear library, have a look at our available cookbooks examples on github.

You can also browse AeroGear iOS API reference to familiarize yourself with the wealth of options.