Monday, May 13, 2013

Customize Your Mobile Service Endpoints

In my previous post I spoke about how Mobile Services is good at giving you a REST endpoint where you can store data.  This time I want to show off what you can do with node.js as data is read/inserted through these endpoints.  These are very common operations that we often handle as part of our REST calls.  It further illustrates how node.js JavaScript comes to serve as your server side logic code.

Reading

Normally when you make a request to a Mobile Services table (or endpoint) request.execute() is called causing an array of JSON objects to be returned comprising the contents of the table (or subset if a filter is provided).  While this is the general use of READ, what about a cause where you want to augment to return with some additional data.

As part of the demo for my Mobile Services talk, I want to pass the READ the token of the device and return back a listing of the stored channels with a boolean field indicating whether the device is registered with that channel.  To do this, I will have to talk to an additional table to determine whether the device is registered.

I will point out that due to some of the decisions made by Mobile Services this process is not as clear cut as you would expect it to be, especially if you commonly work with .NET.  For one thing, any database operation has a callback, operations are not synchronous (despite being on the server).  With that in mind, our first goal is to read out the stored channels from our Channels table:

    var channelTable = tables.getTable("Channels");
    channelTable.read({
        success: function(results) {
            var returnResult = [];
            results.forEach(function(result) {
                var channelName = result.Name;
                var channelId = result.id;
                
                returnResult.push({
                    Id: channelId,
                    Name: channelName,
                    Registered: false
                });
            });
            
            returnWithRegistrationStatus(returnResult, token, request);
        }
    });

We get a reference to our table (Channels) and then simply call readread takes a single parameter which allows us to define options (the documentation does not seem to list what other options exist), one of these supported options is a success callback; you will find this pattern used throughout server side coding using MS, I am still undecided on whether I like it or not.  It is because of this pattern that I had to structure this relatively simple and straightforward operation is such an interesting way.  As I create my return result set, I default the IsRegistered to false.  But notice, the JSON object I am creating is not indicative of the schema for Channels, it is entirely custom and is what we will return once we update IsRegistered,

The second part of this is the returnWithRegistrationStatus method call.

function returnWithRegistrationStatus(results, token, request) {
    var assocTable = tables.getTable("ClientChannels");
    assocTable.where({
        Token: token
    }).read({
        success: function(regs) {
            regs.forEach(function(reg) {
                var channel = getChannel(reg.id, results);
                if (channel != null)
                    channel.Registered = true;
            });
            
            request.respond(200, results);
        }
    });
}

With this block, a read is performed following a where call on the ClientChannels table.  In the case of where, you simply pass a JSON object representing what data you are looking for.  We then analyze the results and update the IsRegistered flag as appropriate.  The final important aspect to this function is the request.respond(200, results) which effectively terminates the read call sending the 200 response code, with results serialized as JSON objects.  This is your response.Content on the other end.

I should also point out how I got the token value into the read call.  This is the C# code from the device which makes call to the read operation of the Channels endpoint.

var table = client.GetTable("channels?token=" + url.AsToken());
var result = await table.ReadAsync(string.Empty);

Notice, that I am using GetTable with a query string, it is read in the endpoint like this.  The string.Empty call is effectively an empty filter.  Since we arent actually using the filter directly in the read call, this really is irrelevant in this case.

var token = request.parameters.token;

Simple.

Inserting

One of the other common operation is a multi tier insert.  In my case, when I attempt to associate a client with a channel, I want to check if that client is registered.  If it is not registered I want to insert it and then perform the association.  As with the read operation, this normally simple operation requires a bit of thinking to work with the callback structure of the calls we will use.

    var clientTable = tables.getTable("Clients");
    clientTable.where({
        Token: item.Token
    }).read({
        success: function (results) {
            if (results.length == 0) {
                console.log("creating the client");
                RegisterClient(item.Token, item.ClientType, item.ChannelId, request);
            }
            else {
                console.log("associating the client");
                RegisterWithChannel(item.Token, item.ChannelId, request);
            }
        }
    });

Here, depending on whether or not the given client (identified by the token principally) we will call a different function.  This is similar to the read in that it users a where call combined with read.  Registering a client is nothing more than inserting a record into the Clients table.  Here is the code for RegisterClient:

   1:  var clientTable = tables.getTable("Clients");
   2:      console.log("inserting client");
   3:      clientTable.insert({
   4:          Token: token,
   5:          ClientType: clientType
   6:      }, {
   7:          success: function(result) {
   8:              console.log("associating the client");
   9:              RegisterWithChannel(token, channelId, request);
  10:          }
  11:      });

Pretty straightforward, as with most operation, simply pass a JSON object to the operation as allow Mobile Services to figure things out.  In this case, in addition to the standard id column, Azure Mobile Services will create two additional columns: Token, ClientType.  Upon the successful completion of this operation, the script moves to perform the channel to device association.  Here is the code for RegisterWithChannel:

function RegisterWithChannel(token, channelId, request) {
    var assocTable = tables.getTable("ClientChannels");
    console.log("adding association");
    assocTable.insert({
        Token: token,
        ChannelId: channelId
    });
    
    request.respond(200);
}

This is similar to the RegisterClient method. It inserts a token and channel Id into the ClientChannels table.  Interestingly, it seems that if you perform this operation from within the trigger, the trigger does not get repetitively called.  I was worried about this, because we are effectively inserting into the table whose Insert script is being executed.  The fact that this repetition does not occur further proves that the purpose of scripts is to perform server side logic and act as a front for the incoming data.

The final operation is the call to respond on request which terminates the script.  In this case, I am not returning anything to the calling code, although it is conceivable that you could return a JSON object as the second parameter with additional information.

Closing Thoughts

It is clear that Mobile Services is a work in progress.  While the editor for these scripts is very nice and I applaud Microsoft for providing a good developer experience it is still lacking.  Right now, the best means of debugging are going to be calls to console.log.  I have no doubt this will improve, but for the moment it can make development tricky.  Also, the documentation (http://msdn.microsoft.com/en-us/library/windowsazure/jj554226.aspx) could use some elaboration and additional examples.

By far the most annoying this is the structure of these scripts.  Operations that should be straightforward and simple require much thought to adhere to the callback pattern.  I would prefer to simple call <someTable>.read() and work with the results that way as opposed to relying on callbacks which can make code messy very quickly.  This in conjunction with the reliance on console.log make developing complex scripts difficult.

Sunday, May 05, 2013

Your Mobile Service as a REST Endpoint

One of the things I like about Azure Mobile Services is how the integration with node.js gives you the ability to quickly generate a compliant REST API along with quickly standing up backend persistence.  Using node.js and the operational triggers attached to each created table, you can very easily perform all sort of data operations and produce common REST like behavior.

A Bit About REST

This is something of a soapbox for me.  REST is not strictly related to web services, it is designed to be much closer to the metal than that.  If we think about web service technologies such as SOAP, we see something that is built on top of HTTP, adding additional overhead to provide additional functionality.  This is different from REST.  REST is about using what HTTP gives us rather than supporting an RPC style web service.  Instead of thinking about calls to the API as functional calls, REST has us think of them as if the user were simply browsing; thus we can rely purely on HTTP for all matter of things.

Take for example, errors.  Very commonly I see developers returning “error” objects from REST; this is, in my opinion, not correct.  HTTP already has errors and error codes, in fact you run into them every day, ala the infamous 404 error.  In a pure REST implementation, if you user was not found you would return a 404 from the server, not an error object.  Your client code would then interpret it.  If the user attempts to access a resource to which they do not have access, the servers returns a 401 (Forbidden).  In short, REST is about using what HTTP gives you, rather than building on top of HTTP as is the case with something like SOAP.

Back to Mobile Services

Azure mobile services provides an endpoint for each table you create.  So if you create a table called “People” you have an endpoint: http://<mobile service name>.azure-mobile.net/tables/People.  Using this endpoint you can send a variety of verbs (POST, PUT, DELETE, GET).  Depending on which verb is used will indicate which node.js trigger is invoked as a precursor to the action operation.  Here is the mapping:

  • POST => Insert
  • PATCH => Update
  • DELETE => Delete
  • GET => Read

At minimal, the script must call request.execute() which indicates the operation should be processed.  You can add conditional logic, ie validation, and use request.respond, which will allow you to pass back an HTTP status code along with a message.  In the case of invalid data, you would not call request.execute().

I admit, I find it rather strange to use the PATCH verb over put to invoke UPDATE, it definitely tripped me up when I first started playing with updates.  However, according to the Azure team, because the default functionality does property –> column matching, it in conceivable that a subset of properties could be sent thus “patching” the existing object, as opposed to a full scale update which is what the PUT verb is commonly associated with.

But how does it know?

So you may be thinking, how does DELETE and UPDATE know what to update.  The answer is, the id column.  Each table in Azure Mobile services is REQUIRED to have an id column, in fact it is automatically created when the table is created.  These operations will automatically key off this id.  Here is an example of the URL to the endpoint:

https://pn.azure-mobile.net/tables/Notifications/1

This will update the record in the Notifications table with the id of 1.  You would pass a JSON object in the request body with the values to replace with.

So what is the result?

The reality is REST is designed to work with resources, its not really designed for endpoints per se.  It is designed so you can query a resource in different ways and perform actions based on those verbs.  With that in mind, I really find what Microsoft is doing with Mobile Services very cool.  Not only do they provide a backend that is easy to work with, they are also allowing developers to quickly implement REST API on those tables/resources using node.js.

For reference: http://msdn.microsoft.com/en-us/library/windowsazure/jj710108.aspx

Thursday, April 18, 2013

SignalR and Azure Websites Error

SignalR and Azure Websites Weird Error

Working with some finishing touches making my Push Demos more consistent I started encounter a failure with SignalR when I deployed to my Azure Website.  I had to deploy the JS code with a debugger; statement and then use Chrome to get the actual error:
"The data protection operation was unsuccessful"
I am still working to understand what this actually means but in the meantime Stack Overflow was once again useful in finding a way around this problem: http://stackoverflow.com/questions/15393684/signalr-cryptographicexception-on-azurewebsites

It seems to be related to the Cryptography settings on Azure Websites, I hope to provide more useful information later.  For now, I hope to save people anguish by at least offering a solution.

Update

After conversations with David Fowler and Damian Edwards (the creators of SignalR) I have discovered the above implementation is extremely insecure and not recommended.  The problem is actually the usage of a custom Dependency Resolver for SignalR.  Because mine is custom, to allow dependency injection via Ninject, I was not getting the provided IProtectedData dependency.  The answer, for Ninject is the following block:
_container.Bind<IProtectedData>().To<MachineKeyProtectedData>();
This will correctly fix the problem and maintain security.  Cheers

Wednesday, April 17, 2013

Windows 8 Access Forbidden

I was doing some development last night on some demo apps and I ran into this lovely error message:

“An attempt was made to access a socket in a way forbidden by its access permissions 192.168.1.18:80”

I got this exception when I attempted to access a Web API service I wrote from my Surface while doing some Remote Debugging.  I kept getting errors indicating the connection could not be resolved.

I did some digging and came up with the exception above, and it seems the solution isn’t overly obvious.  You have to check the following box:

image

This only seems to apply when you are talking to a server internally.  But it might apply elsewhere.  Real annoying, hopefully this posts save some people some time.

Friday, April 12, 2013

Push Notifications with Azure

Recently I have been working on a new talk for speaking engagements.  The topic is Push Notifications which is something which come to the forefront more and more for app development.  As this happens the various OS players have continued to enhance the Push experience within their platform.  The talk was aimed at explaining Push Notifications, their importance, and how to support them in a cross platform way.

Having used Parse in the past I immediately defaulted to using it for the Android and iOS side of my talk, it seemed logical. I was midway through my presentation when I attended a talk at Chicago .NET Developer Group which focused on using Azure as a backend storage for Windows 8 apps.  Now, I had heard about Mobile Services and knew that Microsoft had been working to develop this service.  But I had heard it was limited to only Apple outside of the Microsoft stack and that it was still a work in progress; the talk, done by Adam Hoffman, showed me how wrong I was.

I know from experience that doing push notifications, even on Windows Phone, is not easy and requires a lot of knowledge about XML and the networking stack; so imagine my shock when I realized that Mobile Services could not only handle this for me for my Windows apps but also my iPhone and Android apps.  That with a single line of JavaScript run through node.js on Azure Mobile Services I could easily send notifications to any platform I desired.  And finally, imagine my glee when I saw the setup and just how remarkably easy it was.  Needless to say, my jaw about hit the floor and I promised Adam to check out Mobile Services over the weekend to see if I could fit it into my talk.

Forget fitting it in, I dont think I will ever use Parse again.  Over the course of one weekend I went from being behind in the development of my demo to being ahead of schedule.  I was able to completely overhaul my demo apps architecture and replace it with something that is very clean and consistent.  And, most importantly, I got consistent functionality from Android, iPhone, and Windows Phone apps.

Using the node.js + data table integration point, I was able to write a simple JavaScript script file which handles all of my push notifications for all of my clients, the details for those clients is stored elsewhere as the one shortcoming of the Mobile Services REST API vs Parse is the lack of an endpoint for sending a Push Notification via REST; I am sure the team will address this, in the meantime we have the Storage Table REST API which I was able to use in its stead.

The other nice thing is since Mobile Services uses SQL Azure as the storage mechanism you can access it with SQL Server Management Studio.  In this way you can view your data and interact with it in a much more robust way than with Parse (I cant speak to other services like Urban Airship or Pusher).

I do not want to give away the details of my talk on this post, that will  happen after its debut at Chicago Code Camp on April 27th, but I have to be honest.  What Microsoft is doing with Mobile Services is truly amazing; to think they even took the step of using GCM (Google Cloud Messaging) for Android Push Notifications when most Android devs either arent aware of it or dont use it shows an impressive amount of foresight.

If you havent checked out Mobile Services, do yourself a favor and do it.

Sunday, March 10, 2013

Using Guice in your Android project

Some time ago I wrote the Pay It Square (http://www.payitsquare.com) Android application for a couple friends as a way to promote their service on the Android platform.  Prior to this while I had done Java programming in the past it was not of the “advanced” variety, at least not as high level as what I do in .NET.  This being the case it was my first true exposure to DI in Java.

For DI on Android we used RoboGuice (https://code.google.com/p/roboguice/) which allows for various forms of injection to assist the Android developer in developing the common boilerplate code (ie: getting a reference to a view in a related layout).

For my upcoming talk on Push Notifications talk I wanted to create the Android demonstration app using this tool.  Having been a while since my last big foray into Android I noticed that RoboGuice had recently been updated to version 2.0.  No problem, the instructions (https://code.google.com/p/roboguice/wiki/InstallationNonMaven) seemed clear enough.  However, I quickly found out that something was wrong.

After adding the files as Jar references and then as Library references I kept getting an error relating to the Provider and Class Not Found.  At first I thought I was not referencing the Jar files correctly in IntelliJ.  However, this was not the case.

After breaking things down to their simplest form, I found that a certain Jar file that I thought I had (courtesy of the RoboGuice download) was in fact not correct.  The answer to solving this was to download the files separately:

The problem child here is the javax inject library which supplies the ability for guice to “inject”.  The link above references a ZIP file which contains the javax.inject.jar file.  Add all three of these JAR files as Library references within IntelliJ and everything should work fine.  Leave comments if they dont.

Sunday, February 24, 2013

Create a Sliding Window effect in iOS

As part of my learning iOS I have really started to dig into new aspects of the platform which are challenging me to better understand what iOS and Objective-C offers.  While it has been tough at times due to my familiarity with the Microsoft stack I feel that I am making progress.  One of the effects that is used heavily in Windows Phone applications is the idea of the user being able to slide (using the swipe gesture) from screen to screen; I wanted to duplicate that in iOS.

Approach 1: The ScrollView

Talking with some fellow iOS developers they recommended using a ScrollView and adding SubViews to that ScrollView to represent each of the screens.  I decided to use Storyboards as they appear to be the way forward recommended by Apple for developing UIs, and I really like the tool, it reminds me of what I wish Sketchflow had been.  However, I am finding that in many cases I am having to translate blog entries with use XIB files to Storyboard since most of that content was authored before Storyboards existed.

I found a great tutorial explaining this approach: http://www.iosdevnotes.com/2011/03/uiscrollview-paging/.  Just a word or warning if you intend to use this approach, watch out for 'Auto Layout'.  It appears an issue exists, I can't say for sure if its a bug or not, with storyboards.  This checkbox is checked by default when using Storyboards:

NewImage

When this box is checked the ScrollView will not come back with a size, even though it is set to fill the screen.  This is a problem since the code in the tutorial relies up on the size being there for mathematical calculations.  Deselect this checkbox and the code will work perfectly.

It might be my unfamiliarity with Objective-C/iOS but it appeared with this approach there was no way to load a view controller into the subview.  I didn't want to A) support all of my screens from one view controller and B) I didn't want to mix XIB and Storyboards.  Thus I began looking for an alternative approach.

Approach 2: The UIPageViewController

As it so happens, Apple has a template for this: Page Based Application

NewImage

At the center of this template is the Page View Controller (UIPageViewController).  This appears to be the Apple recommended way to create the effect we are going for.  Its actually quite simple.  I was able to deduce most of the process by analyzing the default code that comes with the template.

Given the application I am working on was already in progress, naturally I didn't start with the Page Based Application as my starting template, so I had to add this functionality in.  Let's walk through how I did this:

1) The very first thing I did was remove my existing "landing screen" and replace it with a Page View Controller.  I then made sure that my original MainViewController was changed to MainPageViewController and inherited from UIPageViewController.  This allowed me to select the controller from the drop down and directly associate the ViewController with the View (the Apple template does not do this, not sure why).

2) With this in place I added three View Controller views to the storyboard.  See, the Page View Controller acts as a container, these pages represent the actual content that will be shown within the container.  If you look at the default Apple template this is was what DataViewController represents, however, they are simply giving this controller different data depending on the month.  Since my application contains three discrete screens for view, with different functions, I need to create each screen individually.  Very important, we need to give each of these views an ID that we can refer to them with.  Specify it as the StoryboardId:

NewImage

You should also add some minor UI to each of your screens, this will help visualize if the effect is working or not.  Also, be sure that the Transition Style is set to scroll.  This will give you that nice transition so that it looks to the user like they are scroll:

NewImage

3) Before we get to the wire up, we need to create a controller of sorts to take care of the Data and Interaction portions for the PageView controller.  You can use your existing ViewController for this if you want, but I find that creating a separate class lends itself to better readability and keeps things from becoming congested in the MainPageViewController.  For this reason I created the PageController.  Here is the interface definition from the .h file

@interface PageController : NSObject <UIPageViewControllerDataSource, UIPageViewControllerDelegate>

You can see we are enforcing two protocols, which will dictate the methods available by this class.  However, I also added a couple of my own for ease of use

- (id) initWithViewController:(UIViewController *) controller;

- (OneListScreenViewControllerBase *) getStartingViewController;

These methods will be used by the code later on when we get to the wire up portion.  Lets walk through the methods in this class:

- (id) initWithViewController:(UIViewController *) controller {

    self = [super init];

    

    if (self) {

        // initialize the listing of view controller names

        pageViewControllerNames = [[NSMutableArray alloc] initWithCapacity:3];  // only three pages at present

        [pageViewControllerNames insertObject:@"ListActivity"atIndex:0];

        [pageViewControllerNames insertObject:@"MainListing"atIndex:1];

        [pageViewControllerNames insertObject:@"ListDetail"atIndex:2];

        

        // store a reference to the root view controller

        rootViewController = controller;

    }

    

    returnself;

}

This method is responsible for initializing the PageController (its the constructor for all intents and purposes).  Notice that we create an NSMutableArray with three strings.  These strings match the names you used for StoryboardId in Step 2.  They also represent the order, left to right, of the screens.  Finally, I am creating a reference back to whichever UIViewController is to be associated with this Page Controller.  Since all ViewController inherit from UIViewController it is the most abstract type I can use for this, this allows this to work with anything.  We will need this reference later on.

Note: Below there is a reference to a type ScreenViewControllerBase, this is a custom type I created which inherits from UIViewController and is the base class for all of my "pages" or the views that will be displayed in the container.  This was done so I could write the methods below to more general and not have to hard code which types to return at what indexes.  Here is the interface definition (.h) for this type.

#import <UIKit/UIKit.h>

 

@interface ScreenViewControllerBase : UIViewController

 

@property (strong, retain) NSString *storyboardId;

@end

Now let's discuss the methods in PageController

- (ScreenViewControllerBase *) getStartingViewController {

    return (ScreenViewControllerBase *)[selfviewControllerAtIndex:1

                                                               storyboard:rootViewController.storyboard];

}

Here we are indicating which view should be displayed when the user see's first.  In this case I am starting at index 1, which is in the middle.  You can see the reference to rootViewController to get the storyboard.  This is the reason we used a custom override for init.

 

- (ScreenViewControllerBase *)viewControllerAtIndex:(NSUInteger)index storyboard:(UIStoryboard *)storyboard {

    return [storyboard instantiateViewControllerWithIdentifier:[pageViewControllerNames objectAtIndex:index]];

}

 

The rest of these methods are implemented as per the UIPageViewControllerDataSource and UIPageViewControllerDelegate protocols.

- (ScreenViewControllerBase *)viewControllerAtIndex:(NSUInteger)index storyboard:(UIStoryboard *)storyboard {

    return [storyboard instantiateViewControllerWithIdentifier:[pageViewControllerNames objectAtIndex:index]];

}

This method simply returns the ScreenViewControllerBase that is found at the given index.  It uses a reference to the storyboard to instantiate the view controller based on the StoryboardId.  This is why providing the StoryboardId is important, it allows us to leverage the View -> ViewController associations stored in the storyboard to return the appropriate view controller for a view. 

 

- (NSUInteger)indexOfViewController:(UIViewController *)viewController {

    ScreenViewControllerBase* oneListScreen = (ScreenViewControllerBase *) viewController;

    return [pageViewControllerNames indexOfObject:oneListScreen.storyboardId];

}

You may have noticed that ScreenViewControllerBase also exposed a property named storyboardId.  This was done to handle this method.  Here we are returning the integer position of the view controller (and the view) within our screen set.  This is used by paging to realize when we have reach the end of our listing.

 

- (ScreenViewControllerBase *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController

{

    NSUInteger index = [self indexOfViewController:(ScreenViewControllerBase *)viewController];

    if ((index == 0) || (index == NSNotFound)) {

        return nil;

    }

    

    index--;

    return [self viewControllerAtIndex:index storyboard:viewController.storyboard];

}

 

- (ScreenViewControllerBase *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController

{

    NSUInteger index = [self indexOfViewController:(ScreenViewControllerBase *)viewController];

    if (index == NSNotFound) {

        return nil;

    }

    

    index++;

    if (index == [pageViewControllerNames count]) {

        return nil;

    }

    return [self viewControllerAtIndex:index storyboard:viewController.storyboard];

}

These two methods work in conjunction with each other depending on the direction the user swipes.  One decrements the index and one increments it.  Both return nil to indicate the end of the road.  It would be possible, I presume, to simply add reset logic in these methods such that you can do a wraparound.

4) The next step is a bit boring.  We need to define a view controller (that inherits from ScreenViewControllerBase) for each view in our content.  In my case I added three:

#import "ListActivityViewController.h"

 

@implementation ListActivityViewController

 

- (void)viewDidLoad

{

    [super viewDidLoad];

    

    self.storyboardId = @"ListActivity";

}

 

- (void)didReceiveMemoryWarning

{

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}

 

@end

 

#import "MainListViewController.h"

 

@implementation MainListViewController

 

- (void)viewDidLoad

{

    [superviewDidLoad];

    

    self.storyboardId = @"MainListing";

}

 

- (void)didReceiveMemoryWarning

{

    [super didReceiveMemoryWarning];

}

 

@end

 

 

#import "ListDetailViewController.h"

 

@implementation ListDetailViewController

 

- (void)viewDidLoad

{

    [super viewDidLoad];

    

    self.storyboardId = @"ListDetail";

}

 

- (void)didReceiveMemoryWarning

{

    [super didReceiveMemoryWarning];

}

 

@end

 

You notice that as of right now there isn't much going on in any of these classes, but importantly look at the assignment of storyboardId and recall the purpose of this property from Step 3.  This is a textual identifier to aid in view controller look up.

After you have created these classes (remember they should ALL inherit from ScreenViewControllerBase) assign them to each of the normal View Controller visualizations on your storyboard

NewImage

We are now done with our setup, time to do the actual wire up.

5) Most of this is going to happen in our MainPageViewController, that is the controller which is acting as a container for the other views.  So lets look at the viewDidLoad method

- (void)viewDidLoad {

    [superviewDidLoad];

    

    // setup the paging system

    self.pageController = [[PageController alloc] initWithViewController:self];

    self.delegate = self.pageController;

    self.dataSource = self.pageController;

    

    // get the first view

    NSArray *viewControllers = @[[self.pageControllergetStartingViewController]];

    [self setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForwardanimated:NOcompletion:NULL];

    

    [self didMoveToParentViewController:self];

    self.view.gestureRecognizers = self.gestureRecognizers;

}

It really is nice when we properly inherit, if you looked at the default template from Apple and then at this, the simplification makes it night and day, I am simply not sure why the example doesn't use inheritance like it should be used in this case.  In any event, only three sections here.  Since the view controller that we are in is a UIPageViewController we need only indicate the delegate and datasource for handling the paging operations.  We used our custom "constructor" initWithViewController passing an instance of ourselves to the instance of PageController.

Regrettably I have not found out how to do section two from the Storyboard yet, I am certain there must be a way, but for now we call our custom method to return the first view controller we want the user to see. Something that confuses me here is that it wants an array of view controllers, yet we only pass a single one.  This is consistent with the Apple example.  Evidently, we are leaving it to our datasource logic to dictate the next controller.  This is in line with how many other platforms do similar data sourcing operations.

I will be honest, I am not entirely sure what the last two lines are doing.  But they seem to be required and are copied directly from Apple's example.

That is it.  Everything should be working now.  I have listed some common problem points below if you have trouble:

I get no UI when I start

Check that you are specified the "Initial View Controller" on one of your view controllers

My transition curls instead of scrolling, like a book

You need to set the transition type to Scroll.  See the very end of point 2.

I see my initial view but I can't scroll

Check the logic in your page controller datasource, make sure it is incrementing properly.  Also, you HAVE to make sure the Storyboard Ids are set properly otherwise you will not be able to find the view controllers from the storyboard.  This will more than likely cause your application to crash instead of simply not working

Leave a comment if there are any additional problems