how to display section view from pasring xml result for iphone - iphone

ok here is the code
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
#pragma mark parse DetailXml
//XMLAppDelegate *appDelegate=(XMLAppDelegate*)[UIApplication sharedApplication].delegate;
Book *aBook = [appDelegate.books objectAtIndex:indexPath.row]; i need this to get id form XMLa
**uuidd=aBook.uniqueId;** this i need
if(bdvController == nil)
// Book *aBook = [appDelegate.books objectAtIndex:indexPath.row];
bdvController = [[BookDetailViewController alloc] initWithNibName:#"BookDetailView" bundle:[NSBundle mainBundle]];
//XMLAppDelegate *appDelegate=(XMLAppDelegate*)[UIApplication sharedApplication].delegate;
//Book *aBook = [appDelegate.books objectAtIndex:indexPath.row];
DetailXml *aDetail=[appDelegate.dxml objectAtIndex:indexPath.row];**i want this as my next table secition view will be based on this XMlb but i am gettingf index out of bound
bdvController.aDetail = aDetail;**
then here xml paresing is done then this
[self.navigationController pushViewController:bdvController animated:YES];
}
i am getting index Out of bound if i do this DetailXml aDetail=[appDelegate.dxml objectAtIndex:indexPath.row];

You can't just specify the number of sections, you also have to tell the table view which cells are in which specific sections.
Depending on how you set up -tableView:cellForRowAtIndexPath:, you may only be returning table view cells for one section.
If you don't specify more than one section (via indexPath.section) when creating cells, then you will get an out-of-bounds error in -numberOfSectionsInTableView: if you return more than one section there.
You might post code for -tableView:cellForRowAtIndexPath: so we can see what's going on there. But that would be the first place I would look.

Related

Tracking UITableViewCells

I have a to-do list app with a bunch of tasks. Each task has a UITableViewCell. After each table view cell is tapped, it creates a view controller with the task at that row's index path's property. These view controllers are all stored in a NSDictionary. This is the code representation of what I just said:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
DetailViewController *detailVC;
if (![self.detailViewsDictionary.allKeys containsObject:indexPath]){
detailVC = [[DetailViewController alloc]initWithNibName:#"DetailViewController" bundle:nil];
[self.detailViewsDictionary setObject:detailVC forKey:indexPath];
detailVC.context = self.managedObjectContext;
}else{
detailVC = self.detailViewsDictionary[indexPath];
}
Tasks *task = [[self fetchedResultsController] objectAtIndexPath:indexPath];
detailVC.testTask = task;
[[self navigationController] pushViewController:detailVC animated:YES];
NSLog(#"%#", self.detailViewsDictionary);
}
So this method of creating unique view controllers and storing them with a certain key almost always works. The problem arises when I delete or move the view controllers:
I was under the impression that a cell's gets recycled as you scroll down (dequeue). This means that marking each cell with a number identifier would result in multiple cells for the same identifier.
Also, if you stored each view controller with a indexPath key, how do you make sure the key isn't set to two view controllers..? For example. Let's say you have 4 cells, which means 4 view controllers. You delete cell 3. Cell 4 moves down to cell 3s spot. You create a new cell which goes to spot 4. Now you have two controllers with the same indexPath key! How do you avoid this?? It's screwing up my app right now because tasks that have already been moved are loading their properties in the wrong view controller/cell!
I was suggested this to solve the problem before: "You maintain an NSMutableArray that "shadows" the contents of the table." I was also suggested to use tags. However, I don't understand what how to implement these.
edit: ---random string---
In tasks.m
-(NSString *)uniqueIdentifierString{
static NSString *alphabet = #"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXZY0123456789";
NSMutableString *s = [NSMutableString stringWithCapacity:20];
for (NSUInteger i = 0U; i < 20; i++) {
u_int32_t r = arc4random() % [alphabet length];
unichar c = [alphabet characterAtIndex:r];
[s appendFormat:#"%C", c];
}
return s;
}
In tableviewcontroller.m
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
DetailViewController *detailVC;
Tasks *task = [[self fetchedResultsController] objectAtIndexPath:indexPath];
if (![self.detailViewsDictionary.allKeys containsObject:task.uniqueIdentifierString]){
detailVC = [[DetailViewController alloc]initWithNibName:#"DetailViewController" bundle:nil];
[self.detailViewsDictionary setObject:detailVC forKey:task.uniqueIdentifierString];
detailVC.context = self.managedObjectContext;
}else{
detailVC = self.detailViewsDictionary[task.uniqueIdentifierString];
}
detailVC.testTask = task;
[[self navigationController] pushViewController:detailVC animated:YES];
NSLog(#"%#", detailVC);
NSLog(#"%#", task.uniqueIdentifierString);
}
One solution would be to decouple your VCs from the table cells. You could store the VCs in your dictionary referenced by an ID that is unique to the task, but not worry about the table cell. If the task is moved or deleted, you can handle that elsewhere without worrying about the VC array being instantly wrong.
Your other option would be to hook into the move/edit methods the logic for iterating over the VC array to adjust the array at that time.
Given that UITableView expects cells to be reused, you can see how it isn't meant to be a storage mechanism for other data.
It would be best to decouple the data so that you aren't bound to the order or existence of them.

In-app populating of UITableView with Xcode? (iPhone)

I'm brand new to Xcode and Objective-C, and fairly new to programming in general so please correct me if I have a severe misunderstanding.
Here's what I'd like to accomplish:
Create a Table View (empty upon startup)
Have user add and name cells via a Bar Button (pushes to a different view with a name Text Field and "Create" button I'm assuming)
Each created cell pushes to a new Table View with similar add/naming functionality
Then each of those cells push to a Text View
It seems to me that the best way to accomplish the first part is by populating a string array, then assigning those elements to the corresponding cells. That's where I get stuck.
How do I populate a Table View with an array?
Should I create a new secondary Table View for every cell, or just populate the same one differently depending on which parent cell is selected?
And same question as previous for the Text Views at the end of the chain...multiple Text Views or just different text passed each time?
If you got this far, I sincerely thank you and please let me know if I need to clarify anything.
I hope you know how to create a table view.
Now you should create a NSMutableArray to save your strings.
#property (retain) NSMutableArray *stringsArray = _stringsArray;
so your viewDidLoad will look like this.
- (void)viewDidLoad
{
[super viewDidLoad];
UITableView *myTableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStyleGrouped];
myTableView.dataSource = self;
myTableView.delegate = self;
[self.view addSubview:myTableView];
[myTableView release];
self.stringsArray = [NSMutableArray array];
}
Now the table view delegates
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [self.stringsArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tmpTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"MainCell";
UITableViewCell *cell = [tmpTableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (nil == cell) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
cell.textLabel.text = [self.stringsArray objectAtIndex:indexPath.row];
return cell;
}
Now when you click on your barbutton to add new user, you must add it to strings array and just call [tableview reloadData];
I didn't understand why you want a text view.
Hope this helps!
Read from here for complete reference of uitableview UITableView Tutorial : Introduction to iPhone TableView

Calling a New View when selecting a Row in a 'UITableView'

I am currently writing my first iPhone app, but have encountered an issue. I have a view which contains a UITableView. This is the first time that I have attempted this, and this is the behaviour that I am trying to achieve:
When the user selects one of the rows, I would like this to call a new view, taking the user to a different page displaying info in reference to what they have selected.
I have it currently, so when the user selects a row it displays a UIAlert in the same view, but this doesn;t suit my needs. I have set the UITableView up through interface builder, and inputted the following code into my .m file to set it up.
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section {
//return the value
return 10;
}
//now we define the cells.
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// Identifier for retrieving reusable cells.
static NSString *cellIdentifier = #"MyCellIdentifier";
// Attempt to request the reusable cell.
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
// No cell available - create one
if(cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:cellIdentifier];
}
// Set the text of the cell to the row index.
cell.textLabel.text = [NSString stringWithFormat:#"iPad %d", indexPath.row];
return cell;
}
This creates a list of ten rows. The following codes gives me my UIAlert when tapped, however, I want to remove this and make it call a new view of my choice;
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Show an alert with the index selected.
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:#"iPad Selected"
message:[NSString stringWithFormat:#"iPad %d", indexPath.row]
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
}
Can anyone help with this last piece of code? the view I want it to call is called 'ProteinView'.
Alrighty, what we need to do is use one of the UITableView methods that are already readily available to us. We'll do the following.
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
ProteinView *detailViewController = [[ProteinView alloc] initWithNibName:#"ProteinView" bundle:nil];
// It is here we'd pass information from the currently selected UITableViewCell to the ProteinView.
// An example of this is the following.
// I would do it like this, but others would differ slightly.
NSString *titleString = [[[NSString alloc] initWithFormat:#"iPad %d",indexPath.row] autorelease];
// title is an object of detailViewController (ProteinView). In my own instances, I have always made a NSString which in viewDiDLoad is made the self.navigationBar.title string. Look below for what my ProteinView.m and .h would look like.
detailViewController.stringTitle = titleString;
// ...
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController release];
}
EDIT
// -------- ProteinView.m -------- //
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
// Here we set the navigationItem.title to the stringTitle. stringTitle is declared in the .h. Think of it as a global scope variable. It is also propertised in the .h and then synthesized in the .m of ProteinView.
self.navigationItem.title = stringTitle;
}
I haven't compiled this, so I don't know if it'll fully work. But that is definitely the fastest and most easiest way to do it!
You could present the view modally like this
YourViewController2 *viewController2 = [[YourViewController2 alloc]initWithNibName:#"YourViewController2" bundle:nil];
[self presentModalViewController:viewController2 animated:YES];
Do you have more than one view to present? If so you will need to create an array with the names, pass it into the tableview and then present the correct view for the row selected based on the indexPath.row.
you'll have to open your MainWindow.xib and add a navigation controller to it. Then add a navigation controller outlet to your app delegate and connect them. Then you'll need to set the navigation controller's view as your main window's view.
You can add a table view to any iPhone app fairly easily, just by creating a new UITableViewController subclass from the File -> New command.
Even if you go this route, I would suggest creating a new navigation-based project to use as a template/cheat-sheet.

How do I set a detail view's title from the selected row?

I have a table view made up of an NSArray of instances of a custom object. When a row in the table view is tapped, it is supposed to trigger a detail view made up of a web view.
So, in MainViewController.m, I have the following:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
MObjectDetailVC *mObjectDetailViewController = [[MObjectDetailVC alloc] initWithNibName:#"MObjectDetailVC" bundle:nil];
mObjectDetailViewController.detailURL=[[[mcData objectAtIndex:indexPath.section] objectAtIndex:indexPath.row] object.url]];
mObjectDetailViewController.title=[[[mcData objectAtIndex:indexPath.section] objectAtIndex:indexPath.row] object.name]];
[self.navigationController pushViewController:mObjectDetailViewController animated:YES];
[mObjectDetailViewController release];
}
However, I get an error for both that start with mObjectDetailViewController: Expected ']' before '.' token. and I don't know why. Can you help? Thanks!
UPDATE: I reduced the amount of square brackets, but I still have the error on each of those lines. It's just that instead of 3 of that error on each line, there's just one instance for each.
You have extra square brackets. Try this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
MObjectDetailVC *mObjectDetailViewController = [[MObjectDetailVC alloc] initWithNibName:#"MObjectDetailVC" bundle:nil];
mObjectDetailViewController.detailURL=[[[mcData objectAtIndex:indexPath.section] objectAtIndex:indexPath.row] object.url];
mObjectDetailViewController.title=[[[mcData objectAtIndex:indexPath.section] objectAtIndex:indexPath.row] object.name];
[self.navigationController pushViewController:mObjectDetailViewController animated:YES];
[mObjectDetailViewController release];
}
At the end of the lines that were giving me issue, I called object.url and object.name. This was unnecessary and invalid. I just needed to put url and name to get those variables from my selected object.
Thanks for your help!

is therea method like did select section in table view

i want to show data of section in a separate view if user touches that particular section..
can any body tell me how to do that?
Use -tableView:didSelectRowAtIndexPath: and just test the indexPath.section property, e.g.:
switch (indexPath.section)
case kFirstSection:
[self doSomethingWithCustomViewForSection:kFirstSection];
break;
case kSecondSection:
[self doSomethingWithCustomViewForSection:kSecondSection];
break;
...
default:
break;
heres what i used. basiaclly what they said but if you want to load ina detail view of some kind here:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
DetailViewController *detail = [[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:nil];
detail.item =(MWFeedItem *)[items objectAtIndex:indexPath.row];
// ...
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:detail animated:YES];
[detail release];
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
}
note: MWFeedItem is one of my classes. you should use your own
If you mean that you want to catch the tap on the section header (the text that you return from tableView:titleForHeaderInSection:) then I'm afraid it's impossible...
You might use the tableView:viewForHeaderInSection: instead and add a transparent button on top of the text. You might also add a transparent text to this button that will hold the section index. This way you can point all the section header buttons to the same selector and in that selector you will have the section (the text of the button)...
You can use indexPath.section within the didSelectRowAtIndexPath: method to determine the section of the cell selected
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
NSLog(#"%i",indexPath.section);
}
The above will output to the console the section that the user has selected