Model-View-Controller in practice on iPhone dictionary app - iphone

I'm a new developer creating a simple "dictionary" app for personal use and my question is about how to properly implement the Model-View-Controller design in my particular situation. Please bear with me for the necessary background:
I want to be able to hit a button and have a label display a word on one side of the screen, and to have another label display a list of associated words on the other side.
For instance: when I hit the button I want the main label to display "cats" and for the list to display "tiger", "snow leopard", "lion", etc. The output would be random: the label displayed would be random and the list would be scrambled.
I've achieved this output in the Xcode 4.3 console through storing each list in an NSMutableArray, and using an NSDictionary to hold all of the NSArrays. Here is the code:
//creates lists
NSArray *catList = [NSArray arrayWithObjects:#"Lion", #"Snow Leopard", #"Cheetah", nil];
NSArray *dogList = [NSArray arrayWithObjects:#"Dachshund", #"Pitt Bull", #"Pug", nil];
...
//creates dictionary and stores lists values with dictionary keys
NSMutableDictionary *wordDictionary = [[NSMutableDictionary alloc] init];
[wordDictionary setObject: catList forKey:#"Cats"];
[wordDictionary setObject: dogList forKey:#"Dogs"];
...
//randomizes selection of dictionary key
NSInteger keyCount = [[wordDictionary allKeys] count];
NSInteger randomKeyIndex = arc4random() % keyCount;
//displays selected key, which is the main word
NSLog(#"%#", randomKey);
//selects array list corresponding to key
NSMutableArray *randomlySelectedArray = [wordDictionary objectForKey:randomKey];
//shuffles the output of the selected word list array
for( int index = 0; index < keyCount; index++ )
{
int randomIndex = arc4random() % keyCount;
[randomlySelectedArray exchangeObjectAtIndex:index withObjectAtIndex:randomIndex];
}
//prints word list and removes displayed dictionary selection
NSLog(#"%#", randomlySelectedArray);
[wordDictionary removeObjectForKey:randomKey];
(I need to add code that does displays a main word and list one at a time, maybe using NSTimer, but this is what I've got so far.)
Using a single-view template in Xcode, I've been able to get the simulator to show a main word and a corresponding list by adding some of this code to the IBAction method of the button in my view controller implementation file. (Of course I changed NSLog to initWithFormat.) However, none of my randomization code works.
My question, finally, is how do I separate things so that they conform best to the MVC design? I'm thinking that: My button and my two labels constitute the view. My view controller is the controller, and my NSArrays and NSDictionary data are the Model.
However, I've been keeping all of my model data inside the view controller, which I'm pretty sure is wrong. I think that I need to figure out how to create a class for my NSArrays and NSDictionary to store my model data. Then I must manage to get my button & labels to display the desired text of my model data via my view controller. At least I think that's how MVC works.
I'm wondering if that understanding is correct and if anyone has any pointers on how to organize my model data most effectively to get my desired output.
Thanks very much for any help! I'm stuck!

Before starting to design an application based on MVC. We first need to know what these different components are and what MVC help us to achieve?
Why we use MVC?(Model-View-Controller)
Because it helps us in:
Separating responsibilites also leads to reusability
By minimizing dependencies, you can take a model or view class you’ve already written and use it elsewhere
Think of ways to write less code
While designing an application based on MVC, we should focus on above points.
Lets relate this 'Dictionary' application with real world dictionary.
A dictionary is composed of words, their meaning, pronunciation, examples, usage, antonyms, synonyms, indexes and other similar information.
When a user wants to look for a particular word he will use top-margin word for fast look-up. Once he found the right page he will go to that word and see its meaning, usage or other needed information.
Model Part:
Lets draw analogy between your application and what I described above.
In your application you will be having a class : 'Dictionary' which
will represent the real world dictionary. This dictionary is composed
of words, their meaning, pronunciation, usage and other information.
So we will need an array of words which will contain 'Word' object.
The 'Word' class will have all the information that we wish to provide
for particular word. You can also provide other attributes that you
can think of that belongs to Dictionary and add them to it.(Here we are talking about content only)
Now we need to think of different operations to be performed on this dictionary. The most basic operation are creating a dictionary and accessing it.
We will have a DictionaryCreator class which will add all the words that our dictionary will have. So this is another class
'DictionaryCreator'. Or we can put this creating logic in 'Dictionary'
init methods. But it will be helpful to have this class this will
enable the dictionary add-word features.
Once DictionaryCreator creates a dictionary, User will be ready to use it. So we will need to provide different operations that a user
can perform on 'Dictionary' as its methods. In our case we can
consider user is over controller, which in fact is controlled by real
user.
The above techique will help you to create a component that performs only its responsiblity and can be reused in other application or extended for future use.
*Always remember Model is the most reusable component of MVC design. So whenever you are in doubt about Model just go remind the words 'Model must be reusable'.
(Not aware of views or controllers)
So we have just finished Model part of the application.
View Part:
This depends on you, what interface you wish to provide to user. But lets again consider the real world Dictionary. A real world dictionary's content(information) is spread across several pages. This view helps us to view/access/mark/bookmark in dictionary.(Remember that here user performs all the operation and not the pages neither the dictionary). The pages have easy look-up word on top or bottom and some pronunciation guidance at bottom.
In your application you said "I want to be able to hit a button and have a label display a word on one side of the screen, and to have another label display a list of associated words on the other side."
Here we have again have multiple options to implement this, you can create view using Interface Builder and connection them with your controller. But then again this controller and View will be tightly coupled and when we wish to use similar interface somewhere else we will be unable to do so. So for reusability we will create another UIView class and create it with a new View XIB and load this nib. So in future if you need similar kind of view you can easily reuse(like cocoa-touch provides us UIView, UIButton etc.).
*View also tends to be a reusable component in MVC.
(Not aware of controllers, may be aware of relevant model objects)
Controller Part:
Now we have created view and model but how will they communicate? Controller will help them in this. A controller :
Knows about model and view objects
The brains of the operation
Manages relationships and data flow
Typically app-specific, so rarely reusable
*The points and definition I have taken from Stanford University Lectures[CS193P - Lecture 6
iPhone Application Development
Designing iPhone Applications Model-View-Controller (Why and How?) View Controllers]
Update:
Recently, I have come across another good lecture on MVC. It explains this design concept in much better way with very nice examples. It is available at iTunes U or you can directly go to first lecture by iPad and iPhone Application Development (SD) by Paul Hegarty.

Related

How to follow MVC if you have lot of static data?

I am developing an iPhone application in it I am having around 15 arrays and 15 more array which has value in it corresponding to the value in array e.g. NSArray *XYZ = {a,b,c,d} and array NSArray *ABC = {w,x,y,z} such that value 'a' corresponds to 'x' .Can comebody tell me what is the best way to follow MVC in this scenario like I have to make function (returning array) for each array in another class or should I make class for every array.
I would write all your business logic as classes with those arrays in a MODEL file, access those classes from the CONTROLLER file. And then once you have all your data, access from the CONTROLLER the VIEW file to output. Inside the MODEL write functions for those arrays so that you can reuse them, if they vary they may need own functions. This is a helpful link: http://php-html.net/tutorials/model-view-controller-in-php/ and those videos give you a taste of the logic behind MVC: http://www.youtube.com/watch?v=HFQk8WGK1-Q&feature=bf_prev&list=UU9-GXsmQQ-N4h8ZsKI8CSkw

How do I "connect" a table view to a view controller

Alright, I know this is a vague conceptual question, but I really need help here. Thanks in advance if you decide to take the time to read this. I would never even consider writing this much except this is such a great forum with so many helpful people I thought this would be the best place to ask.
This is all related to the question here (you don't have to look at it - I explain everything below): Pass parameter when initializing table
I've been working for days on the same problem, but I'm realizing there must be something big I'm missing. I've googled and googled and I even bought (and about 50% read) two Obj-C books a few days ago, but I'm still grasping at something that seems like it should be incredibly easy. I'm obviously pretty new to OOP, but I have mediocre skills in HTML, perl, sql, python as well as some of the ancient stuff like pascal and basic. I'm a n00b, but not a moron (well, actually this experience is changing my mind a bit).
Anyway, my end goal here is to simply create an app with 8 "normal" buttons on the first view (level 1), each doing basically does the same thing - which is to show a simple table view (level 2) with data in cells that can be clicked to continue to drill down to details (level 3). Very basic and straightforward concept. The only difference between the 8 possible level 2's is the data that will be shown. I've already constructed sql queries that work just as I want for each button.
So, here's where I stand: I have a perfectly working app that does everything from level 2 down exactly as I expect - the queries work, the tables are beautiful - so that's great.
Also, I have another nav-based app that launches on "level 1" and shows me 8 buttons (I hide the nav bar on level 1). If I click any of the buttons on level 1, the level 2 view (which is a nav bar + a table) slides into view exactly like I want. The problem is the table is just blank. No matter what I do, I can't get the level 2 in the second app to show me the data, even though I can show all of that data in the first app perfectly. For the life of me, I can't figure out how to "link" level 1 with level 2.
Hopefully you can understand this gap I'm trying to bridge. Since there are 8 possibilities for level 2 (with only very slight differences in sql queries on the same sql table), I initially tried coming up with a way of "passing" an integer to the level 2 view (in the first app) and then selecting the sql query based on what was passed (see the link above for that fiasco). Once I got that working, I planned to figure out how to make the buttons do the "passing" later. However, after about 16 hours screwing with that, I just gave up and decided to make 8 different table view controllers, all with nearly identical code except the query. That way, if I could just get a SINGLE button on level 1 to simply push to just ONE of the level 2's with NO parameters I would be a horrible but successful programmer.
Unfortunately, even that hasn't worked out for me. I have tried every possible control-drag and window/view/table combination I can think of in Interface Builder, but no matter what I try, the data never loads into the table view, even though it works great in my first app. I have gone through every line of code - they are the same except something has to "call" or "launch" the level 2 part and I'm just not getting it.
So, I'm going to break with convention/expectations here and not post any code in my question. I just want to know - how can this possibly be so difficult?? I am very analytically minded and I catch on quickly, but I have to say I have never been so humbled by a technical challenge in my life.
Can anyone explain to me, at a conceptual level, what I need to be doing here or what I'm missing? Even if you give me a link to something to read I would appreciate it very much. I have watched tens of hours of tutorials on youtube, but I'm always up for more.
Of course I'm willing to share my code, but there is so much of it and I'm so new at this I really don't know where the relevant parts are. Plus, I actually want to learn how all of this works so I can help others. If there is such a thing as PM on here I'll email it to you if you're willing to take a look. Once I get it working, I will post the code here. I have to believe there are other people looking for the same kind of thing as I am. However, more importantly, I just want to know, from a high level, what is the correct way to approach my problem? If you look at my link you can see what I've been trying (which was to pass an integer to the method that populates the table), but as I said, I basically gave up on that because I wasn't getting anywhere. People are trying to help me, but I'm an idiot.
Thanks for bearing with my agonizingly long message. If you made it this far and have some suggestions for me I'm all ears. I'll be honest, though - if you tell me I should just scrap the whole thing and use core data I'll cry. I really don't think I have the time to figure out a whole different way of managing data. As I said, I'm pretty happy with the database and the query parts of my app - it's just managing the freaking views and passing data between them that is killing me!
Any help is appreciated - thank you all so much.
If I understand your question correctly, you are asking how to initialize a view controller and pass in some data to alter its behavior. The key concept here to understand is how objects are initialized in Objective-C. One of the most common questions that developers who are new to iOS have is:
How can I pass data between my views?
Yes, eight different links there. (Okay, that eighth link is a little bit off topic, but it's close enough.) There are several ways of doing this and I'll go through them briefly. I'll also describe custom initializers, which are a relevant point as well.
Let's pretend we were building a catalog application which shows a bunch of products in various categories. Imagine that our app opens to a list of products, much like the Apple Store App. Say that when the user taps on a product we want to show a product page.
You can set properties on the "next" view controller. - Simply, we can create a UIViewController subclass and set the productID property (which we made up). Let's call our new UIViewController a ProductPageViewController. Here's how this would look:
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
//Create a ProductPageViewController
ProductPageViewController *ppvc = [[ProductPageViewController alloc] initWithNibName:#"ProductPageViewController" bundle:nil];
//set the property on our ProductPageViewController
[ppvc setProductID:42];
//We would usually present the PPVC here.
//After presenting, remember to release the view controller
}
In the first line, we create the product view controller. We call alloc, then init. (The functions are wrapped - that is, we call init directly on the result of the alloc method.)
Then, we set a property of our view. The view can now be configured in viewWillAppear and all is well.
You can share the data through a persistent store. - This method works a little differently. The view controllers don't communicate at all, except for the first one presenting a second one. Whenever a value in the first view changes (that you want to persist), you write it to Core Data or NSUserDefaults. Then, the new view reads the value as it needs it.
In your first view controller:
//A method to store the data
- (void)storeData:(id)pageID{
[[NSUserDefaults setObject:pageID forKey:#"pageID"];
}
- (void)showNewPPVC{
ProductPageViewController *ppvc = [[ProductPageViewController alloc] initWithNibName:#"ProductPageViewController" bundle:nil];
//Show and then release the PPVC
}
You can use custom initializers. - This is probably the most intuitive way to do it, once you understand the concept, because this is the only one where data is actually "passed". (As opposed to method 2 where no data is directly shared and method 1 where data is passed as a property.)
Notice that in the earlier examples, I used the initWithNibName:Bundle method. You might also notice that UITableViewControllers use a different initializer, initWithStyle:. Those two initializers take in some information for the new object so that it knows how to load. Let's look at the first one first:
- (id)initWithNibName:(NSString *)nibNameOrNil Bundle:(NSBundle *)bundleNameOrNil;
The first argument tells the view controller which nib file to load up. I'm going to ignore the second argument for now, since I've never seen anything passed in except nil. Moving right along to the second example:
- (id)initWithStyle:(UITableViewStyle)style;
You can pass in one of two UITableViewStyle values here. This is one way to define the style of a table view (the other way being to modify a nib file directly).
Let's extend this concept a bit to our example. I'm now going to show you how to make your own custom initializer. Let's initialize our ProductPageViewController instance:
- (id) initWithProductID:(int)productID;
That's simple enough. Now, we need to implement the method and actually do something with the product ID. We'll start with the barebones code here, required to "mimic" the functionality of the default initializer.
- (id) initWithProductID:(int)productID{
self = [super init];
return self;
}
This method will return an initialized copy of our ProductPageViewController, however, it won't load up our UI from a NIB yet, or if this were a UITableViewController, it wouldn't set the UITableViewStyle. Let's work with a NIB first and then I'll show how to work a UITableViewController. So...
- (id) initWithProductID:(int)productID{
self = [super initWithNibName:#"ProductPageViewController" Bundle:nil];
return self;
}
Now. we have an initialized ProductPageViewController, loaded from a NIB, but it doesn't do anything yet. Notice how we don't expose the NibName and Bundle arguments, but we just pass them in ourselves. If you want, you could theoretically expose those too. Now, let's take that productID and do something with it.
- (id) initWithProductID:(int)productID{
self = [super initWithNibName:#"ProductPageViewController" Bundle:nil];
if(self){
self.prodID = productID;
}
return self;
}
With our latest changes, our "PPVC" now knows about the productID. It can query the database as you want and do things with the results. You can then run different queries based on this productID.
Two More Quick Tips:
Perhaps you want to pass in several arguments. Of course you can simply add them to them method signature - (id) initWithProductID:(int)productID andCategoryID(int)categoryID, but what happens if you have five, six, or fifty six (yea, that's a lot) arguments? I'd advise passing in a collection or array of arguments.
To use custom initializers with UITableView, you pass in a UITableViewStyle instead of a NIB name. Here's what it might look like:
- (id) initWithProductID:(int)productID{
self = [super initWithStyle:UITableViewStyleGrouped];
if(self){
self.prodID = productID;
}
return self;
}
When making your subsections, I'd suggest a combination of persistent data and custom initializers. I also advise taking a peek at the viewDidLoad and viewWillAppear methods.

Practical efficient usage of IBOutletColletion

How does look the practical usage of IBOutletCollection? Unfortunately Apple documentation mentions it briefly without giving an wider idea of usage. OK, it maintains one-to-many relation with IB, but how to access and use particular objects efficiently? With TagName? How to ensure the order of objects?
I've recently used this to easily initialize a grid of labels. I have a n by n matrix of labels on a view, and reference each one individually (via an IBOutlet) in order to display relevant data. However when the view first loads I wanted to control the default text that displayed in all the labels. Initially i wanted a dash to display, but since this is for a client I wanted it to be easy to change. The view contents have and continue to change over time, per client requests.
Instead of writing N line of code, I created an IBOutletCollection and accomplished the same results in 4 (#property, #synthesize, and for loop). YMMV but I found it very useful in this situation.
Read again this section in the Interface Builder User Guide.
IBOutletCollections are actually just NSArrays you can connect to more than one object in IB. All the objects you connected end up in this array and can be accessed from code like any other object in an array.
I used it to minimize code. I have a range of UIViews that should react on "touch up inside" events of some UIButtons (custom mode).
I gave all UIButtons a tag (lets say 1005 to 1010) and all UIViews the same tag as the UIButton they shall respond to.
Then I connected the UIViews with the collection in Interface Builder. All UIButton touch up events go to the same function in my controller. This function gets the tag of the sender object, iterates through the NSArray list (of "IBOutletCollection(UIView)") and compares the tag. Everytime it hits, the appropriate action is done.
It is a pity that NSArrays seem not to hold the order...

Re-usable Obj-C classes with custom values: The right way

I'm trying to reuse a group of Obj-C clases between iPhone applications. The values that differ from app to app have been isolated and I'm trying to figure out the best way to apply these custom values to the classes on an app-to-app basis.
Should I hold them in code?
// I might have 10 customizable values for each class, that's a long signature!
CarController *controller = [[CarController alloc] initWithFontName:#"Vroom" engine:#"Diesel" color:#"Red" number:11];
Should I store them in a big settings.plist?
// Wasteful! I sometimes only use 2-3 of 50 settings!
AllMyAppSettings *settings = [[AllMyAppSettings alloc] initFromDisk:#"settings.plist"];
CarController *controller = [[CarController alloc] initWithSettings:settings];
[settings release];
Should I have little, optional n_settings.plists for each class?
// Sometimes I customize
CarControllerSettings *carSettings = [[CarControllerSettings alloc] initFromDisk:#"car_settings.plist"];
CarController *controller = [[CarController alloc] initWithSettings:carSettings];
[carSettings release];
// Sometimes I don't, and CarController falls back to internally stored, reasonable defaults.
CarController *controller = [[CarController alloc] initWithSettings:nil];
Or is there an OO solution that I'm not thinking of at all that would be better?
I would personally consider some kind of "settings" class, in the tradition of Objective-C data sources. Set up a class that's responsible for being a "data source" for each individual app: have it provide either a set of methods for the values you need for that particular app, or a single "getValueForKey"-style method that returns the appropriate value.
Either way, the solution:
Keeps values in code
Removes the overhead of one massive plist for every setting, some of which may not be used
Removes the work of splitting out bunches of tiny plist files
Allows you to have other classes call your data source wherever they need it
Gives you the flexibility of OO (you could, in theory, subclass your data source should the situation or need arise)
Localizes the changes you need to make; just include the data source class as part of the set of classes you're reusing from app to app, and tweak just that class as appropriate (rather than having to change things throughout other classes)
Lets you set reasonable defaults - or even throw exceptions - for data values you don't expect to be needed in a particular application, without the need for explicit fallback code in every calling class (write the default or exception once in the data source class)
I would give a delegate member to each class to ask what the fine details should be. What font should I use? I'll go ask my delegate. It does not have to be the same delegate for each class or instance, but it can be. For values that can have defaults, use respondsToSelector: to allow for optional delegate methods.
You could make the delegate go look in an xml/plist file for the details, in which case you have it all in one place and can even download a new file to change little details.
All your classes can have the same initWithDelegate: method, which makes it easier to instantiate one without knowing what it is.
Prariedogg,
Absolutely externalize the settings into something like a plist. You can even have multiple plists that align to the particular situation (e.g. settingsMac.plist, settingsIPhone.plist).
When your app determines what environment it is running in, it loads the appropriate settings via a delegate or a central singleton.
By externalizing it you will reduce the average maintenance cost of the application. There is less cost to managing and deploying plist updates than recompile/retest/repackage/redeploy.
-- Frank

Objective C Object Functioning & Passing Arrays

I apologise if this has been asked before but I can't find the info I need.
Basically I want a UITableView to be populated using info from a server, similar to the SeismicXML example. I have the parser as a separate object, is it correct to alloc, init an instance of that parser & then tell RootViewController to make it's table data source a copy of the parser's array.
I can't include code because I haven't written anything yet, I'm just trying to get the design right before I start. Perhaps something like:
xmlParser = [[XMLParser alloc] init];
[xmlParser getXMLData];
// Assuming xmlParser stores results in an array called returnedArray
self.tableDataSource = xmlParser.returnedArray
Is this the best way of doing it?
No, you don't want to do this. You don't want your view controller directly accessing the array of the data-model. This would work in the technical sense but it would be fragile and likely to fail as the project scaled.
As the projects grow in complexity, you will want to increasingly wrap your data model object (in this case the xmlParser) in protective layers of methods to control and verify how the data model changes. Eventually, you will have projects with multiple views, multiple view controllers as well as information entering from both the user and URLs. You need to get into the habit of using the data-model object not just a dumb store you dump stuff into but as an active manager and verifier of your data.
In a situation like this I would have my data-model's array completely wrapped by making it a #protected or #private property. Then I would have dedicated methods for fetching or inserting data into the actual array inside the data-model class itself. No objects outside of the data-model should actually have direct access to the array or have knowledge of its indexes.
So, in this case your data-model would have something like:
- (NSString *) textForLineAtIndexPath:(NSIndexPath *) anIndexPath{
//... do bounds checking for the index
NSString *returnString=[self.privateArray objectAtIndex:anIndexPath.row];
if (returnString=='sometest'){
return returnString;
}
return #""; //return an empty string so the reciever won't nil out and crash
}
as well as a setTextForLineAtPath: method for setting the line if you need that.
The general instructional materials do not spend enough (usually none) time talking about the data-model but the data-model is actually the core of the program. It is where the actual logic of the application resides and therefore it should be one of the most complex and thoroughly tested class in your project.
A good data-model should be interface agnostic i.e. it should work with a view based interface, a web based interface or even the command line. It should neither know nor care that its data will be displayed in a tableview or any other interface element or type.
When I start a new project, the first thing I do is comment out the '[window makeKeyAndVisible];' in the app delegate. Then I create my data-model class and test it old-school by loading data and logging the outputs. Only when it works exactly how I wish it to do I then proceed to the user interface.
So, think real hard about what you want the app to do on an abstract level. Encode that logic in a custom class. Isolate the data from all direct manipulation from any other object. Verify all inputs to the data before committing.
It sounds like a lot of work and it is. It feels like overkill for a small project and in many cases it is. However, getting the habit early will pay big dividends very quickly as your apps grow in complexity.
Not quite. You want the data source to be an object that implements the UITableViewDataSource protocol; what I would do in this situation is create an object that implements that protocol and parses XML, so that you can alloc-init it, then set the data source to that object and have it update the table view as appropriate. So based off your code (and assuming you're running within the table view's controller):
XMLParserAndDataSource xpads = [[XMLParserAndDataSource alloc] init];
[xpads getXMLData];
self.tableView.dataSource = xpads;
It's probably a good idea to give this class itself a reference to an NSXMLParser object, so you can use that to parse the XML, then provide convenience methods (like getXMLData) as well as the UITableViewDataSource methods for your own use. (If you go this route, you should also make your XMLParserAndDataSource class implement the more useful of the NSXMLParser delegate methods, and use them as appropriate to update your table view.)
I'm a Mac programmer and not an iPhone programmer; but on the mac,
self.tableDataSource = xmlParser.returnedArray is not correct. You are supposed to either bind the table's content to an Array Controller (if iPhone has one?) or set the datasource outlet to your RootViewController.
In your rootview controller, you would implement the methods:
– tableView:cellForRowAtIndexPath:
– tableView:numberOfRowsInSection:
For – tableView:cellForRowAtIndexPath: you would return a UITableViewCell with the data you received from the XML parsing according to the index path like so:
UITableCell *myCell = [UITableCell new];
myCell.textLabel.text = [parsedXMLArray objectAtIndex:[indexPath indexAtPosition:indexPath.length-1]];
return myCell;
(Something people don't know is that you can use the + new class method on all NSObject subclasses which automatically call alloc/init.)
For – tableView:numberOfRowsInSection just return the count of the data array:
return parsedXMLArray.count;
Can't edit my question nor post replies, can only post my response as answer.
#TechZen: I'm somebody who tries to form analogies, helps me understand. What you're saying is something like: My original idea was like going into the file room & dumping all the originals on my desk to work on where as you suggest the object be more like an organised file clerk who will search through the data for me and only return the specific datum that I need while being the only one with direct access to that data.
Have I understood correctly?
#Tim: What if I later need the parser to get data for something which is not a table? That's why I thought to dump it into an array & let the caller decide what to do with the data. Would you suggest a second object that would supply the data in the newly required form? (Am I sort of one the right track here or way off?)