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

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.

Related

Model-View-Controller in practice on iPhone dictionary app

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.

Access UIView's textview from other view

Hello I have an app with 2 views.
The cybeeview and the moreview.
I use the cybeeview to do some calculations and I want to present them in the second view.
How can pass the data from cybeeviewcontroller.m to the moreviewcontroller??
Good way would be to use delegation. You can either write your own protocol, or implement - textViewDidEndEditing: inside moreviewcontroller. You will also need to set up the delegate:
cybeeviewcontroller.yourTextView.delegate = moreviewcontroller;
//those controllers are instances of their respective classes
Nonetheless it must be said that unless it is a minor and unimportant calculation you're doing, it's fair to say that you are not doing it correctly. You should be setting your model values and pass model around. You can get more information in documentation, look for Model-View-Controller design pattern.

Core data refactoring

Hi
Normally all the methods like
'- (NSFetchedResultsController *)fetchedResultsController '
are placed in the code of view controllers. I find it a bit messy to write Data Fetching code along with lifecycle methods or table delegate methods.
So my point is should I refactor the CoreData methods to some other helper class say DataLoader and then call them in view controllers?
Is this a wrong thing to do or am I going to loose some coding benefits of Core Data methods.
I would say moving the fetchedResultsController to a helper class is a good idea.
A problem I encounter often is to get the spelling of attributes right.
For example I do a predicate and want to filter on an attribute called #"isSelected". There is no check by the compiler nor by the linker to check the string isSelected. I will have to double check each line where the string has been used.
A search&replace won't work on the misspellings because I don't know what bugs have been introduced.
When I get the predicate wrong then no results will be fetched. Problem is that I don't know if there are no matching rows or if I have filtered wrong. I will need to check at runtime and that consumes time.
For predicates the saved templates exist, so predicates are not a perfect example. But think about value forKey: and we are at square one.
Now if all the fetchedResultsController are in one file then checking would become easier. At least it reduces the possibility of missing that little misspelling in a far away and rarely used class.
...or am I going to loose some coding benefits of Core Data methods.
I tend to say no, but other please feel free to jump in.
#Mann yes of course you can do that without loosing any coding benefits.....if u don't want to write Data Fetching code in you view Controller do not write there.....Make any other class lets say it DataLoader and write the fetching code in method of this class......and call this method by making the object of DataLoader class ....u will be able to fetch data from database
Hope u get it!

Changing cell appearance when editing UITableView _without_ using custom cells?

If I am using a custom UITableViewCell I can use the following methods to change the cell's appearance when transitioning state:
- (void)willTransitionToState:(UITableViewCellStateMask)state
- (void)didTransitionToState:(UITableViewCellStateMask)state
Is there a way to achieve this if I'm not using a custom tableview cell?
Edit: Please see Daniel Hanly's comment. Categories may be selectively applied using #import. My apologies to anyone that may have been misled by this answer. Relevant sections will be redacted for future reference.
Okay, attempt number two. As far as I am aware, there is no other documented way to implement the functionality you require without subclassing UITableViewCell. It's worth noting that Apple's docs on UITableViewCell specifically mention that the state transition methods are meant to be implemented by subclasses. That having been said, If you absolutely need to implement them without a subclass, there are a couple of less conventional solutions. Each comes with its own issues, and it may end up being unfeasible for you to implement them, but it's an interesting question nonetheless.
Disclaimer
If you only want a sane and relatively simple explanation, then consider the answer to your question to be "no, there is no way to do what you want." I only present the options below with the assertion that they will work. In no way do I endorse actually using them. Consider this my penance for providing my first answer with such an obvious flaw.
Option One - Categories
It is possible to get the functionality you're looking for by overriding the methods you listed in a custom UITableViewCell category.
The problem is that this approach would be a pretty bad idea 99% of the time. Once you define the category on UITableViewCell, those methods would be defined for all UITableViewCell objects throughout the app. Unless you want the exact same state transition functionality for every single table cell in the app, this approach isn't very helpful.
Option Two - Runtime magic
You can use the low-level Objective-C runtime functions to change the implementation of any method on the fly. Unlike the categories option, this approach is flexible enough to redefine the intended behavior whenever you need to, instead of being a one-shot deal.
For example, if you're trying to manage state transitions from a UITableViewController, you could do this:
CustomTableViewController.m
#import <objc/runtime.h>
- (void) customStateWillChange:(UITableViewCellStateMask)state
{
//custom UITableViewCell code
}
- (void) viewDidAppear:(BOOL)animated
{
//Store the original implementation
Method originalStateWillChangeMethod = class_getInstanceMethod([UITableViewCell class], #selector(willTransitionToState:));
originalStateWillChangeImplementation = method_getImplementation(originalStateWillChangeMethod); //variable declared in header file as type IMP
//Get the new implementation
Method newStateWillChangeMethod = class_getInstanceMethod([self class], #selector(customStateWillChange:));
IMP newStateWillChangeImplementation = method_getImplementation(newStateWillChangeMethod);
//Replace implementation
method_setImplementation(originalStateWillChangeMethod, newStateWillChangeImplementation);
//the rest of your viewDidAppear code
[super viewDidAppear:animated];
}
- (void) viewDidDisappear:(BOOL)animated
{
//restore the original implementation
Method originalStateWillChangeMethod = class_getInstanceMethod([UITableViewCell class], #selector(willTransitionToState:));
method_setImplementation(originalStateWillChangeMethod, originalStateWillChangeImplementation);
//rest of viewDidDisappear code
[super viewDidDisappear:animated];
}
This code may not suit your exact purposes, but I think it provides a useful example.
It's incredibly ugly though because the customStateWillChange: method defined here is only intended to be run as a part of the UITableViewCell class, but in this example it will be compiled as though it were part of the CustomTableController class. Among other annoyances, you would have to eschew the property dot notation, ignore compiler warnings and give up most if not all compile-time checks for that method's body.
Option 3 - Category with runtime magic
Exactly what it sounds like. Define any custom state change methods you like within a category (or several categories) on UITableViewCell. Be sure that each one has a separate name - adding two categories that each have a method of the same name will result in undefined behavior. Also, each one needs to have the same return type and argument types as the method it is intended to replace.
Then the references to [self class] in the above code would be replaced with [UITableViewCell class], and the customStateWillChange: method would be moved to the custom category. While still ugly, you can at least rely on the compiler to interpret the method bodies properly.
Of course, messing with the runtime adds a whole lot of complexity to keep track of. It could work fine, but it's not good design, it would take serious effort to ensure it worked safely and correctly, and it would be likely to bring anguish and despair to anyone maintaining it.
References
The Objective-C Programming Language - Categories and Extensions
Objective-C Runtime Reference
Absolutely. The UITableViewDelegate protocol specifies a number of methods to manage state transitions for the table view's cells. Take a look at the UITableViewDelegate Class Reference, specifically the methods listed under the heading "Editing Table Rows".
Edit
Sorry, you're right. The UITableViewDelegate methods don't respond to direct changes to the cell's properties. I've found a way that does work, but I'm going to put it in a different answer to avoid confusion.

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?)