KVO with SPO5 and STSOData
Stan Stadelman

#Introduction to STSOData and SP05, Part 2 I’ve done some work with colleagues over the past several months, to develop a template of best-practice implementations of the SAP Mobile Platform SDK 3.0 SP05 features. I’m providing this as both a reference implemenation, and a reusable template framework that you can drop into your own application project, to bootstrap your development, while significantly reducing the lower-level details you need to manage in your app.

This reusable template code is called ‘STSOData’, and I introduced it here. This post is Part 2 of the introduction, and starting from where we left-off in Part 1, with our Model added, and fetch requests added to the DataController, we’re going to bind our UI to the travelAgencies NSArray property on the Model.

##Hands-on implementation

##How to?
What we’re doing in this example, is basic Apple Cocoa KVO. Our problem will be: bind the value of an NSArray property on our Model singleton, to the UITableView cell content in the MasterViewController. So, we’ll wire up the view controller to trigger a fetch: request by the DataController, then observe the [Model shared].travelAgencies property.

###Where to trigger fetch:

We’ll kick off our fetch: request from within -viewDidLoad:. This is probably the most typical place to put this type of request, though it can also work well to put them in -viewWillAppear. It depends on where in your navigation heirarchy the view controller happens to be, and what code is associated with the segues between your views.

For example, your view controller might be navigated away-from and back-to several times in the application flow if it is close to the root; if the higher level views are mostly read-only, then you might want to use -viewWillAppear, since this is most likely to pick up changes on the server. But, if your higher level views are write-centric, it’s likely that you already have refresh code implemented in the submit/segue, so additional checks would be redundant.

###Handle for Logon Finished In this example, we’re actually dealing directly with the rootViewController, so we need to be aware of one other detail: the delegate callback from Logon, when the logon procedure is complete. Our networking stack is dependent on connection settings and credentials, that are only guaranteed to be available after the Logon procedure is finished. Once the application has registered the first time with its server, this happens very quickly on subsequent launches, but is is an asynchronous operation.
So, to encapsulate this wait, we listen for an NSNotification which our LogonHandler emits, named kLogonFinished. By using the block variant of the -addObserverForName: method, we can then kick-off the fetch request at the right time.

###Adding observer to Model There are also a variety of places in the view controller where we could add the observation for the travelAgencies property on Model. In this case, we’ll use -viewWillAppear:, and we’ll remove the observer in -viewWillDisappear:. This gives us a good balance for simplicity, and ensures we won’t run into any exceptions with orphaned observations.

If using this approach of add/removing the observer dynamically, we should listen for both NSKeyValueObservingOptionNew and NSKeyValueObservingOptionInitial. We always assume that .New will give us changes, but since the Model property may already be populated, .Initial will give us the current state.

###Handling initial and new values to [Model shared].travelAgencies Once the observers are in place, we need to implement -(void)observeValueForKeyPath:, to handle the observation messages. In this case, we simply check if the keyPath is equal to @"travelAgency". If equal, then we’ll reload the tableView.

It’s up to you how to handle the change notification. If you’re expecting minor changes occasionally, you might use tableView:insertRowAtIndexPath:animated:, for a smoother user experience.