Web Services project and the Tab view Controller


#1

Hi:
I’m wondering if someone can help me out with this small puzzle based off Chapter 21 Web Services and Chapter 7 View Controllers.

What I’m trying to do is add RSSTableViewController from Chapter 21 to the project HypnosisViewController as another tab named TopSongs. I can easily setup HypnosisViewController with an additional tab and everything seems ok, but the data from TopSongs will not show in the TableView. Is there a trick to making the data display? My NSLog statements are still intact and I can see the Webservice calls and returns data when I click on my “Songs” tab, but the tableView in RSSTableViewController doesn’t seem to get loaded. All I see is a blank tableView. Any ideas on how to make this work?

On another note once this gets resolved, is there a way to call the webservice then cache the results? I don’t want to hit the webservice everytime someone clicks on the “Songs” tab since the data won’t change.


#2

Ok, this is getting scary. I figured it out!
This is great testament to this book, going back to Chapter 2 I found the answer. All I had to do was add this to my init statement. [self initWithStyle:UITableViewStylePlain];

Now on to figuring out a way not to repeatedly call the web service once I’ve got the data. (Any good ideas is most appreciated)


#3

There are many ways to handle this, and at different levels. However, the basic procedure is to:

  1. call the web service
  2. store the results
  3. use the stored results each time the tab is displayed

I realize that this doesn’t say much, in fact its quite obvious, but its important to think in terms of design and program flow, and drill down. To implement these steps, you must make decisions within each major step. For example:

Step 1: Call the Web Service
Where to call it? the 2 likely candidates are:

  1. up front when the app is first loaded, ie in the AppDelegate’s

The downside to this approach is that normally you want to put off operations until needed, because sometimes you may not need them. You potentially spend time doing stuff you don’t need to do. For example, if the user never touches the Songs tab, there would be no reason to waste the performance time on going out to the web server and retrieving data. Now, “putting it off” is not always the best approach, because it is highly dependent upon your application. However, its good general rule.
2. The first time that the TopSongs tab is selected. To implement this, you can create a simple iVar flag for the TopSongs view controller indicating whether or not it has been displayed previously. This one follows the “put it off” rule.

@interface RSSTableViewController : UITableViewController { BOOL firstTimeDisplayed;

then conditionally execute the web service call:

[code]- (void)loadSongs
{
// In case the view will appear multiple times,
// clear the song list
[songs removeAllObjects];
[[self tableView] reloadData];

if (firstTimeDisplayed)
{
    firstTimeDisplayed = NO;

// construct the web service URL
NSURL *url = [NSURL URLWithString:@"http://ax.itunes.apple.com/"
			  @"WebObjects/MZStoreServices.woa/ws/RSS/topsongs/"
			  @"limit=10/xml"];
			  				  
// create a request object with that URL
NSURLRequest *request = 
	[NSURLRequest requestWithURL:url
				 cachePolicy:NSURLRequestReloadIgnoringCacheData
			 timeoutInterval:30];
			 
// clear out the existing connection if there is one
if (connectionInProgress)
{
	[connectionInProgress cancel];
	[connectionInProgress release];
}

// Instantiate the object to thold the data
[xmlData release];
xmlData = [[NSMutableData alloc] init];

// Create and init the connection - non-blocking
connectionInProgress = [[NSURLConnection alloc] initWithRequest:request
													   delegate:self
											   startImmediately:YES];
}

}
[/code]

You will also want to set firstTimeDisplayed back to YES if there was an error in the web service call (ie, - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error)

Step 2: Store the results
How and where to store the retrieved data? This decision would be dependent upon your actual application. For the app you describe, you only need the data in the TopSongs VC, therefore, store it there. If you were building an app that may want this data other places, there may be a good reason to keep it somewhere more centralized. In general, always compartmentalize the data to the lowest level of need, and design to support a high degree of modularization.

For your app, there doesn’t seem to be any reason why you wouldn’t store it exactly as defined in the TopSongs example: ie, in the TopSongsVC.

Step 3: Use the storage each time the tab is displayed
Again, real app vs this app comes into play here. In your app, the data is quite static, and there would be no reason to do anything different than the TopSongs example does. In a real app, if the data were not quite as static, you would want to make sure you were calling “reloadData” on the tableView in the proper areas so as not to display stale data.

Hope this helps!


#4

Thanks Jmac1163. Heck yea this helps a ton. I have a tendency to over-think things. What your saying makes total sense a simple iVar will suit me just fine.

Again thanks for you input and great detailed explanation. I’m sure this will be valuable everyone here.

-Marcus