TableView not displaying parsed data from xml? - iphone

i have tabbar controller, first tab is for Tableview controller.but i do xml parsing in appldidfinish method , in the xml parse didEndElement, i calculate items count and i give
it into first tab's Tableview controller's numberOfRowsInSection,but after xml parsing finished, the following method wont be called. tableview is empty....?
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [myParser.items count];
}
i have declared in view did load method of that table view controller
myParser = [[XMLMyParser alloc] init];
any help please.....

When the XML parsing is complete, you need to inform the table view that the data has changed.
You do this by sending the reloadData message to your table view instance:
[myTableView reloadData];
Assuming you're using the NSXMLParser, you will need to add this in parserDidEndDocument message of your NSXMLParserDelegate implementation

Related

Troubles with datasource and tableviews

I've got an UIViewController with 2 tableviews:
1- the main tableview, which is shown in the whole view controller
2- the second viewcontroller, which is loaded in a popup view.
The second tableview is shown on swiping a cell of main tableview.
Depending on which cell is swiped, there are different data in popup view.
I've already loaded the whole data in viewdidload method and stored everything in nsmutablearray, so are ready to be loaded.
My problem is that I don't know how to work with tableview's DataSource, in my project i linked both tableview's datasource to file's owner, but in this way it loads the numberofrows from the main view, and it doesn't take the correct count which should have the second tableview.
So, if in main tableview i have for example 3 elements, and in the second tableview it should load 5 elements, it gives me an error, ('NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index…).
I think that i should link my tableviews to different datasource, even if i really don't know.
I hope to be clear, if you need more info, or a better description, ask me and i'll do it for you.
In the delegate method, you should compare the tableview.
See the example,
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if(tableView == maintableView)
return VALUE_FOR_MAIN_TABLE_DATA;
else
return VALUE_FOR_POP_TABLE_DATA;
}
No Problem
you just set tags to your tables.
[tableView1 setTag:1];
[tableView2 setTag:2];
and then
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
if (tableView.tag == 1) {
return 4;
}
else if (tableView.tag == 2)
{
return 5;
}
}
do similar thing all data source method
You can use one View Controller as an unique data source for multiple table view, but you'll need to check which table view is requesting data using the tableView arguments of the UITableViewDataSource methods.
For example:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView == self.mainTableView)
{
// code for your main table view
}
else
{
// code for your popup table view
}
}
The same instance of a view controller serving as data source/delegate for two tables is technically possible but has a number of traps. One of these is: to which of the two tables does self.view refer?
However, most of the data source protocols hand down a reference to the table. You could use that rerference to determine which table acutally sends the request. But not all methods of the protocol inclulde a reference to the table. And that is where it starts getting tricky.
You are far better off with two distinctive view controllers, one for each table. Establish a protocol between them so that the main view controller can hand down the data to the one in the popup window so that the popup can initialize/load it self with the proper data and can refresh its view when ever the data changes.
You will need to check for the tableview in all your delegate and datasource methods as follows:
if (tableView == mainTable)
{
// code for your main table
}
else if (tableView == popupTable)
{
// code for your popup table
}
You do same for 2 or more table views.
Hope this helps.
You can do it both ways:
Make separate classes as data source for separate tables. Instantiate their objects as datasources for tables and bind them at viewDidLoad method in proper view controller.
Make one datasource for 2 tables which I don't recommend as it is not comply with proper OOAD. You'll have tight coupling this way between view controller and the table which can be cause of trouble in the near future.
You have method - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
in which you can distinguish to which table you are referring:
if (tableView == mainTableView) {
// initialize cell for main table view
}
if (tableView == secondTableView) {
// intialize cell for second table view
}

iphone development: table view returns empty table

I am brand new to iOS development, and I could not find a solution on here or Google, so I'm asking out of desperation.
I have a class "ViewController" that is a subclass of UIViewController. In here, I have:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([self.bookTitle.text length] > 0)
self.entries = [self.bookLibrary searchForBook:self.bookTitle.text];
if ([segue.identifier isEqualToString: #"BookList"]) {
TableViewController *controller = (TableViewController *)segue.destinationViewController;
controller.itemCounter = [self.entries count];
controller.bookLibrary = [self.entries allValues];
}
}
The view for this on the Storyboard has a connection to a Table View Controller that I dragged and dropped onto the grid. I clicked the "Table View Controller" at the bottom, and set my custom class "TableViewController" in the custom class input box.
Now, from what I understand, the method above is passing all the data properly to the TableViewController.
Here's one of the methods I have in the TableViewController
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"BookCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
Book* book = [self.bookLibrary objectAtIndex:indexPath.row];
cell.textLabel.text = book.title;
NSLog(#"%#", book.title);
return cell;
}
The NSLog entry is printing out all the book titles to the console, so I know for a fact the data is being passed. However, when I run the program and click the button to pull up the Table View, it's just an empty table. Any hints? I can upload my entire project. Been at this for several hours and a bit frustrated. Please help :(
EDIT: A response suggested I look at the state of my data variables in the table methods. It suggests their state is not what I think it is and that I should use NSLog to print out their values. I did just that, and I can see all the values printed out. I don't understand... they do infact have values assigned to them. The problem isn't that the data is missing.
Make sure you're either using a UITableViewController subclass as your VC (if you're using a UITableViewController ui object from the pallet), or that you're properly hooking up the UITableView's delegate and datasource properties to your VC (if you're using a plain UIViewController object and subclass).
(see comments on question).
Try this:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog(#"bookLibrary.count %d", bookLibrary.count);
return [bookLibrary count];
}
You'll find that things are not what you think they are... Add in an implementation of viewDidLoad and viewWillAppear along with that, each with their own "I'm here" NSLog statement, and trace the flow of that second view controller appearing. Again, you'll find you've got some sequencing issues where the flow isn't working quite the way you might be assuming.
Added comment:
Ultimately, the origin of your problem is this line in your "sending" controller's prepare for segue method:
controller.bookLibrary = [self.entries allValues];
What is this doing? It's calling allValues on the Dictionary object. That method generates a new array (!) containing the values. You don't store that new Array object in any permanent storage. You just use it to set:
controller.bookLibrary = ...
So, right after that statement executes, you have:
an Array object in your prepareForSegue method (where the code is executing) that you've only stored in one variable/holder, which is:
a weak pointer to that object over in your destination view controller (TableViewController)
The method ends.
The Array returned by [... allValues] is not being held on to by anything in the Source view controller, so the only thing holding it from being garbage collected is the pointer to it in the Destination view controller.
But that pointer is a weak pointer. By definition, if that's the only pointer to an object, the pointer will be set to nil and the object released for garbage collection. Poof! No more array object, and you're left holding a nil pointer.
As you discovered, setting the "receiver" to strong lets it hold on to that Array object, even after the other code exits and it's the only pointer to the Array.
(And, your code isn't being invoked twice. If you look closely at the logging -- or better yet set a breakpoint inside the table get-row-count method -- you'll see it's only being called once. The earlier logging of "I have 8 objects" is happening over in other code, not in your TableViewController.)

self.tableView insertRowsAtIndexPaths from within tableView delegate

So I thought I'd have a go at building my own simple app. Please go easy on me I'm new to all this! The idea is this. For iPad have a single view controller with a text box and a text field. Text box takes a title, and text field takes the body of a report. There's a button on the page to submit the report, which bundles the two texts into an object and adds it to a table view within the same view controller. I have set the view controller as a delegate with <UITableViewDelegate, UITableViewDataSource> in my header file. My table view works fine for adding items in the viewDidLoad method. But adding items from the text inputs via a UIButton connected to -(IBAction) addItem falls over with: Property 'tableView' not found on object of type 'ReportsViewController'
- (IBAction)addReportItem
{
int newRowIndex = [reports count];
ReportObject *item = [[ReportObject alloc] init];
item.title = #"A new title";
item.reportText = #"A new text";
[reports addObject:item];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:newRowIndex inSection:0];
NSArray *indexPaths = [NSArray arrayWithObject:indexPath];
[self.tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationAutomatic];
}
I understand that I'm trying to call a method within my object but I have other method calls to tableView which work fine. i.e.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [reports count];
}
I thought this was the point of delegation. I know I'm missing something, but as I say I am new to all this and have looked everywhere for an answer before posting. What do I need to do to send my IBAction message to tableView?
Do you have a tableView instance variable setup in your .h file of the view controller?
The reason you are able to access it in the delegate and data source methods is because they are passed in as part if the methods.
You will need to add the IBOUTLET tableView ivar and connect it to the tableView in your .xib.
Or perhaps your ivar for the tableView is named something else?
Good luck.
I had the same problem.
What helped was to inherit the View Controller from UITableViewController, instead of UIViewController. Not using the protocol names in angled brackets.
The TableView is then linked to the dataSource and delegate via the storyboard (resp. InterfaceBuilder).
The parent class UITableViewController has an IBOutlet tableView defined.
MyViewController.h:
#interface MyViewController : UITableViewController

UITableView -> numberOfRowsInSection:(NSInteger)section returns wrong value

My 2nd time today... But here are so many good developers...
Hi,
I have some troubles with my tableView... If the view will appear my table reloads its data, but it doesn't update the numbersOfRowsInSection...
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog(#"COUNTER: %i",[content count]);
return [content count];
}
The log says the first time I load the page the right value. But if I add an object and reload the data, this function isn't calling.
Is there anyone who know the solution?
Thanks,
mavrick3.
EDIT:
Heres how I call [table reloadData]
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if ([content count] != 0) {
self.content = [[[[NSArray alloc] initWithContentsOfFile:[FileManager filePath]] objectAtIndex:row_] objectForKey:#"faecher"];
[table reloadData];
NSLog(#"----%#",content);
}
}
And yes, the dataSource and delegate are connected and they are both implemented in my header.
If you call reloadData on a UITableview object and you're it's dataSource then this method should be called called.
Are you sure that you have assigned your table view to your property (i.e. dragged it across in interface builder?)
I suspect that you have only made your controller the dataSource of your table view (hence the first time it loads it gets the value). After that your calls to reloadData won't work because the property in your view controller is still nil.
You can test this by putting an NSLog just before you call reloadData - if it outputs nil then you've not connected it.
NSLog(#"%#", myTable);
[myTable reloadData];
any compiler warnings?
Is "table" actually an instance of UITableView?

iPhone - generic UITableView

I know how to build and display the XML data in UITableView. And let's say I have an UITableView named: "DisplayData"
I have a same three XML documents. All three have same structure. Ex:
Doc1:<data><a>v1</a><a>v1</a></data>
Doc2:<data><a>vx</a><a>vx</a></data>
Doc3:<data><a>ZZZ</a><a>ZZZ</a></data>
What I want to do is - that when user selects a row from allready loaded UITableView - a new instance of same code is loaded onto stack of views.
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
DisplayData *o = [[DisplayData alloc] init];
o.rootElementName = #"data";
o.urlToLoad = self.urlToFolow;
o.urlToFolow = self.parsedURL;
[self.navigationController pushViewController:o animated:YES];
[o release];
}
So basically I want to load different data and detail data with only one UITableView.
You should keep your data in a model object (NSArray ?) and when the user taps on a row you replace the model object with the new data and call [tableView reloadData].
You can also have a look at Apple's Drill Down Table View example...