Monday, August 22, 2011

Cranking out the IOS version

Ok - now that we have advertising enabled in our Android app, at last, the time seem to have finally come to start cranking on the IOS version. The first thing we're going to do is the long threatened opening of current relatively primitive version of the app with the new X Code 4 editor.

Well, I get some kind of "not recognized" message. Some quick googling tells me that it's probably a corrupted download. I'll launch that later when I get home, as I don't want to crowd up the Panera network - it's a huge download, 4.2 gig.

I'll bring it up with the regular editor. What we want to do is get the list to show the same page.

I'm not exactly sure how to proceed. For example, the display it calls currently, AnswersController, implements this method:

-(IBAction)popViewController:(id)sender {

// return to previous screen
[self.navigationController popViewControllerAnimated:YES];
}



I believer this just means it gives an animated, sliding effect when it transfers either to of from the current display.

Here's the method in the calling module which handles the return from the pop:

/* call back method on pop of answer page */

- (void) viewWillAppear:(BOOL)animated{

// NSLog(@"view will appear was called");

// won't be animated on the first call
if (animated) {
appState.currentQuestionNumber++;
[appState saveState];
}

currentQuestion = appState.currentQuestion;

answers = [currentQuestion answerArray];

// triggers reload, see veiwDidLoad method
[tableView reloadData];
}



So, that's all normal. How about where the transfer to the Answers controller occurs?

Here it is:



#pragma mark UITableViewDelegate
- (void)tableView:(UITableView *)tv
didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{


QuizAppDelegate *delegate =
(QuizAppDelegate *)[[UIApplication sharedApplication] delegate];

AnswersController *answersController =
[[ AnswersController alloc] initWithIndexPath:indexPath];

[ delegate.navController pushViewController:answersController animated:YES];
[ answersController release];

[tv deselectRowAtIndexPath:indexPath animated:YES];
}


So, it looks like it's allocating the answersController. The initWithIndexPath is probably a reference to whatever's been selected. And it's deselecting the row so it won't be highlighted when it comes back.

The question I have is, do I want to reference the current instance of the QuestionController (actually called the "rootController" - btw, what is it that makes these controllers, as opposed to delegates?)

Let's review. Here's a nice overview from StackOverflow:

http://stackoverflow.com/questions/3626737/whats-the-difference-between-the-rootviewcontroller-appdelegate-and-the-view-co



In general, delegates can be thought of as event handlers. Accordingly, the AppDelegate is the main event handler for your entire application. It is told when the application has launched, when it will exit, when a Push notification comes in, when the app has gone into the background, etc.

One of those events - applicationDidFinishLaunching - is typically responsible for creating the application's window and adding views to that window.

// Ok, at this point the AppDelegate sort of constructs the UI.

In most applications, the view that is added to the window is actually controlled by a UIViewController. Each UIViewController is responsible for managing the appearance of one main view plus all of its subviews.

// This is actually similar to an Activity in Android, in the sense
// that it's responsible for a given "main" view.

For example, a UITableViewController is responsible for managing a UITableView (main view) and all of the UITableViewCells (subview) that are inserted into that UITableView.


// My app is doing something with table view - I have it in my program:
// @implementation RootController
// @synthesize tableView;


// What did the @implementation do again? I'll figure it out later.


The UIViewController typically acts as a delegate (event handler) to the views it is responsible for. When a user taps a table view cell, a method in the UITableViewController is called. When the user swipes to delete a separate method is called.

// So that's what all the callback are about.
// Well, not all of them. But that's the idea.
// In fact, it's similar to Android, which has
// callback you add like "onButtonPush", and so forth.

A generic UIViewController provides the same basic functionality, but for custom views. For example, the UIViewController may be responsible for displaying a few text views and a button. The UIViewController would create its main view, the text views and the button view. The text views and button view would be added to the view controller's main view as subviews. The UIViewController would register itself as the delegate for events from the text view (for example learning when the user has finished editing the text in the text view).

// This difference between this and Android is you do the event registering yourself.
// It's automatically done in IOS. In a way, I like adding it myself - you understand more what's happening.

It would also register a method to handle a button press originating from the button it owned. When any of these registered events occur, methods on the UIViewController are called allowing you to take whatever action is needed.


The rootViewController is a specific type of view controller used with navigation controllers.


// This is where it gets the thickest. I know the whole point is to move
// from one view to the other - to navigate.

If you want an application that has the typical iOS navigation view hierarchy, your AppDelegate would typically add a UINavigationController to the app's window. That UINavigationController is useless without actually having content to display. That is where the rootViewController comes into play. You are responsible for providing a view controller (such as the one described above) to act as the first view stored in the UINavigationController's stack of views.

// Ok, I think I get it. The "rootController" means the first view delegated to
// by the Navigation controller.


This view will be displayed when the app starts up and anytime that the user pops subsequent ViewControllers off of the UINavigationController's stack.

// The stack verbiage explain "onPop" type methods were were seeing.
// That's why my "question view" is called the "rootController" - a name
// I took from the app I was using as a template.




Ok, so, based on the above, things look a bit different than I had though initially. The root controller is actually not going to be the question display anymore - it's another view, a menu type of view which could dump off to either the (main) question view or a settings view. Unfortunately, it looks like I'll need to overhaul the apps navigation to accomplish this. Hmmph.

We're starting to get back into the world of the IEB controller. Probably the easiest thing will be to start from scratch, and cannibalize from the old app.

I think I need to do this in the new Xcode. Which is the better option?

Maybe, just maybe if I flip the answer for the question, I can revamp the question as the menu screen. So, for that, I'll first rename the rootController as the questionController. Let's try it.

First, let's back it up. How? I have the project in appdev/iPhone. Ok, the project name is different than the file name - we'll have to remedy that.

Ok - that's done. But, again, I'm being pulled inexorably back into the Android world. This issue? The dreaded platform fragmentation.











No comments:

Post a Comment