How to push view depending on the row selection? - iphone

/*****UPDATED** ***/r.com/YH3cm.png
I am trying to figure out in the above image, how will we know if the user has selected Date or Track.
/UPDATED/
The data I am receving is through a select query and I create an array to store the list. It is dynamic and not necessary limited to two fields, it can have 10 fields also. How will I know which row is selected and how will I push the data on to the next view.
Like in didSelectRowAtIndexPath, how should I push the date or track field on the next view?
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (dvController == nil)
dvController = [[DetailViewController alloc] initWithNibName:#"DetailView" bundle:nil];
Teat *obj = [appDelegate.coffeeArray objectAtIndex:indexPath.row];
dvController.obj = obj;
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:dvController animated:YES];
}

It's still not very clear what you're trying to do. If you want to push a certain view controller depending on what the content of the cell is, but there is no definite arrangement of the rows, I would use the row index to access the array that is the source of your data. Some very loose code:
WhateverObject* selectedObject= (WhateverObject*)[tableDataSourceArray objectAtIndex:indexPath.row];
if( [selectedObject hasAnAttributeYouCareAbout] )
{
MyViewController* theCorrectController= whicheverViewControllerYouWant;
theCorrectController.anAttribute= aValue;
[self.navigationController pushViewController:theCorrectController animated:YES];
}
And here's how you can define your UIViewController subclass MyViewController with specific attributes. In the .h file:
#interface MyViewController : UIViewController {
int anAttribute;
}
#property int anAttribute
#end
In the .m file:
#implementation MyViewController
#synthesize anAttribute;
#end
You can have as many attributes as you want of whatever type, and then you can set them with aViewController.anAttribute as above.

Create objects - dateInfoViewController and trackInfoViewController and then...
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSInteger row = [indexPath row];
if (row==0)
{
if (self.dateInfoViewController == nil)
{
DateInfoViewController *temp = [[DateInfoViewController alloc] init];
self.dateInfoViewController = temp;
[temp release];
}
else {
dateInfoViewController.title= [ NSString stringWithFormat:#"%#", [sessionInfoDetailsArray objectAtIndex:row]];
YourAppDelegate *delegate = [[UIApplication sharedApplication]delegate];
[delegate.sessionNavigationController pushViewController:dateInfoViewController animated:YES];
}
}
if (row==1)
{
if (self.vetInfoViewController == nil)
{
TrackInfoViewController *temp = [[TrackInfoViewController alloc] init];
self.trackInfoViewController = temp;
[temp release];
}
else {
trackInfoViewController.title= [ NSString stringWithFormat:#"%#", [sessionInfoDetailsArray objectAtIndex:row]];
YourAppDelegate *delegate = [[UIApplication sharedApplication]delegate];
[delegate.sessionNavigationController pushViewController:trackInfoViewController animated:YES];
}
}

I fear it's not perfectly clear what do you want to do... if you need to push a different view depending on the selected row you may simply do something like
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == 0)
//push view 1
else
//push view 2
}
UPDATE: calling indexPath.row you get the index of the selected row. I guess is up to you to decide what to do depending on what row is selected. To pass this information to the next view you may simply think of a #property field to set, a method to call or a custom init method for the view controller you are pushing. What is the problem with the code you posted?

Related

CellForRowAtIndexPath is not invoked

I'm writing an app hat has many views and I used sliding views library (ECSlidingViews). The problem is when I fill an array with objects and fill the table with the objects in tableView:cellForRowIndexPath: method, it does present the data in the table, but when I go to other view and come back the data disappears because tableView:cellForRowIndexPath: is not called. Here is the code:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"begin of cellForRowAtIndexPath");
SchedualeCell *cell = (SchedualeCell *)[tableView dequeueReusableCellWithIdentifier:#"Cell"];
Course *temp = [array objectAtIndex:indexPath.row];
cell.nameLb.text = temp.name;
cell.hourLb.text = [NSString stringWithFormat:#"%d",temp.hour];
cell.startTimeLb.text = temp.startTime;
cell.endTimeLb.text = temp.endTime;
NSLog(#"End of cellForRowAtIndexPath");
return cell;
}
tableView:numberOfRowsInSection: and numberOfSectionsInTableView: is invoked when I come back to the view that has the table view.
P.S.: The view is UIViewController that has table view inside of it, and I searched all StackOverflow before posting my problem.
EDIT : this is where I set the delegate and datasource
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"Did Appear");
// Do any additional setup after loading the view.
self.view.layer.shadowOpacity = 0.75f;
self.view.layer.shadowRadius = 10.0f;
self.view.layer.shadowColor= [UIColor blackColor].CGColor;
if (![self.slidingViewController.underLeftViewController isKindOfClass:[MenuViewController class]])
{
self.slidingViewController.underLeftViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"Menu"];
}
[self.view addGestureRecognizer:self.slidingViewController.panGesture];
if (array == nil)
{
array = [[NSMutableArray alloc]init];
}
table.delegate = self;
table.dataSource = self;
[table reloadData];
}
and I did included The delegate and datasource in the header
#interface MainViewController : UIViewController<UITableViewDataSource , UITableViewDelegate,addDelegate>
First of all , it's not numberOfRowsAtSection and numberOfTableView. It's numberOfSectionsInTableView and numberOfRowsInSection.
Things you can do :
1) NSLog your numberOfRowsInSection. Note that , If it's "0" then your cellForRowAtIndexPath is never going to be called.
2) If you are using your UITableView inside some UIView then you should add :
[self.view addSubview:table];
3) Don't Forget to include :
#interface yourViewController : UIViewController<UITableViewDataSource,UITableViewDelegate>
Once check that you reframed the tableview in ViewWillAppear.
Some times if we set out of frame, CellForRowAtIndexPath will not call.

NSIndexPath associated with UITableView

I have a table view on my master view, and a textField on my detail view. The app is simple. Add a table view cell with some info. Then if you press the cell, it pushes the detail view and shows the cell's title/text in the text field. In the master view, im using an NSFetchedResultsController. And in the second view, im trying to load the data, but for some reason i am not using my own indexPath variable correctly, because every cell that gets pressed shows the first cells text on the detail view. Code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell =
[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Set up the cell...
[self configureCell:cell atIndexPath:indexPath];
self.path = indexPath;
//I have tried this as well.
//self.path = [NSIndexPath indexPathForRow:indexPath.row inSection:0];
return cell;
}
Detail View:
-(void)viewWillAppear:(BOOL)animated
{
if (self.context == nil)
{
self.context = [(FBCDAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
}
NSFetchRequest *request = [[NSFetchRequest alloc]init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"FailedBankInfo" inManagedObjectContext:self.context];
[request setEntity:entity];
NSError *error;
NSMutableArray *array = [[self.context executeFetchRequest:request error:&error] mutableCopy];
[self setTableArray:array];
FailedBankInfo *infoData = [self.tableArray objectAtIndex:self.root.path.row];
NSString *string = [NSString stringWithFormat:#"%#", infoData.name];
self.nameField.text = string;
string = [NSString stringWithFormat:#"%#", infoData.city];
self.cityField.text = string;
string = [NSString stringWithFormat:#"%#", infoData.state];
self.stateField.text = string;
[super viewWillAppear:YES];
}
Why not just pass the index path into the detail view controller in the
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
method, with a custom initializer:
- (id)initDetailViewControllerWithIndexPath:(NSIndexPath*)indexPath
?
I'm not familiar with a "root" property on a UIViewController, what is that? It seems to be an attempt to reference the first view controller from the detail view controller. Have you checked to see what self.root.path.row is returning?
Anyway the path property of your first view controller is independent of what ever cell is selected the way you have your code. It is simply set to the indexPath of the last cell that is loaded. If you did want to some how access this property from your detail view controller, it would have to be set in the didSelectRowAtIndexPath method, not the cellForRowAtIndexPath method to be accurate.
I think that if you set the path in didSelectRowAtIndexPath your way should work. But to write the custom initializer, add a property to your detail view controller called path, and then add a custom initializer to the detail view controller like this:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil andIndexPath:(NSIndexPath*)indexPath
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.path = indexPath;
}
return self;
}
and call this from the didSelectRowAtIndexPath method of the first view controller using
DetailViewController *detailViewController = [[DetailViewController alloc] initWithNibName:nil bundle:[NSBundle mainBundle] andIndexPath:indexPath];
[self presentViewController:detailViewController animated:YES completion:nil];
(if you're not initializing from a xib, customize which ever initializer that you're using).
Or, instead of passing in the index path, you could pass in an NSDictionary containing the data that you need in the detail view controller (the title and the text).

How to use pushViewController and popViewController

I want to A viewcontroller switch another B viewcontroller,First time,I push(press GuestBook Button)and TableView get information ok,and press back Button ok, push(press GuestBook Button) again,JSON data NSLog have message,but tableview data not appear!
what's happen?
PS:i use storyboard!Have a custom cell xib!
A.m
- (IBAction)toHostGuestBook:(id)sender {
hgbvc = [self.storyboard instantiateViewControllerWithIdentifier:#"ToHostGuestBookSegue"];
hgbvc.eventidStr = eventidStr;
NSLog(#"hgbvc.eventidStr:%#",hgbvc.eventidStr);
[self.navigationController pushViewController:hgbvc animated:YES];
}
B.m
- (IBAction)backToHostMainEventDetail:(id)sender {
[self.navigationController popViewControllerAnimated:YES];
}
B.m
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *GuestBookCellIdentifier = #"GuestBookCellIdentifier";
static BOOL nibsRegistered = NO;
if (!nibsRegistered) {
UINib *nib = [UINib nibWithNibName:#"GuestBookCell" bundle:nil];
[tableView registerNib:nib forCellReuseIdentifier:GuestBookCellIdentifier];
nibsRegistered = YES;
}
gbcell = [tableView dequeueReusableCellWithIdentifier:GuestBookCellIdentifier];
if (gbcell == nil) {
gbcell = [[GuestBookCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:GuestBookCellIdentifier];
}
NSDictionary *dict = [messageRows objectAtIndex: indexPath.row];
gbcell.nicknameStr = [dict objectForKey:#"vusr"];
gbcell.dateStr = [dict objectForKey:#"date"];
gbcell.messageStr = [dict objectForKey:#"message"];
return gbcell;
}
Add this and Try
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.tableView reloadData]; //your table view name
}
try to reload the table view data on below the code of popViewController this is work what you want
hgbvc the B controller is retained by the A controller. so, it doesn't released when the B controller poped out. When the B controller pushed again, the viewDidLoad method not called.
solution: extract the tableview load data method. call this method when you push B.
in B controller:
- (void)showDataWithEventId:(NSString *)eventId
{
//retrive data
//table view reload
}

Inserting data from one table to another table

I have two UITableViewController classes, MainTableController and SubTableController.
From AppDelegate class I am calling MainTableController class.
At first this class is empty, and there is button named "show list" in this class.
When I click on this button I will go to SubTableController and there I have a list of actions in form of table.
Now if I choose to first cell action then that action name has to come on my first cell of table in MainTableController. But I am not able to print that name in table of MainTableController class.
In SubTableController:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
ActionList * actionListObj = [appDelegate.actionArray objectAtIndex:indexPath.row];
self.chooseActions = actionListObj.actionName;
MainTableController * mainViewController = [[MainTableController alloc] init];
[mainViewController getAction:self.chooseActions];
[self.navigationController dismissModalViewControllerAnimated:YES];
}
In MainTableController:
-(void) viewWillAppear:(BOOL)animated{
[self reloadData];
}
-(void) reloadData{
[self.myTableView reloadData];
}
-(void) getAction: (NSString *) actionChoose{
self.action = actionChoose;
[self reloadData];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell...
cell.textLabel.text = self.action;
return cell;
}
When I debug, in MainTableController I am getting the action in getAction method but in table cell text string is null.
Can anyone please help me regarding this?Where am I going wrong?
You are allocating and initializing a new view controller each time you select a cell in SubTableController.
MainTableController * mainViewController = [[MainTableController alloc] init];
and of course, it isn't the one in place in the navigation stack.
You need to make these two controllers communicate.
I suggest that the sub view controller define a property on the main one, in order to message it when needed.
In SubTableController, add a property and synthesize it :
#property(readwrite, assign) MainViewController *mainViewController;
// and ...
#synthesize mainViewController;
Of course when you push the sub view controller, don't forget to set the property.
// in main view controller
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// alloc/init the sub VC
subVCInstance.mainViewController = self;
[self pushViewController:subVCInstance ......
Now when a row is selected in the sub one, message the main one, without alloc/init a new MainViewController object :
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
ActionList * actionListObj = [appDelegate.actionArray objectAtIndex:indexPath.row];
self.chooseActions = actionListObj.actionName;
//MainTableController * mainViewController = [[MainTableController alloc] init];
[self.mainViewController getAction:self.chooseActions];
[self.navigationController dismissModalViewControllerAnimated:YES];
}
This should work just fine.
In didSelectRowAtIndexPath of the SubTableController class, you are allocating new MainTableController to send the data.
MainTableController * mainViewController = [[MainTableController alloc] init];
[mainViewController getAction:self.chooseActions];
You should not do like that. Because the existing mainview will be different from the newly allocated one. You should use delegate to give back the data. For more info on Protocols and delegates, see here
More example here

UITableView with JSON help

I am trying to feed in some JSON data to my iPhone app, the data is coming in fine as I have NSLog's telling me so.
The problem I am having is trying to get the results to show in a UITableView. I have a navigation controller underneath a tab bar controller, the navigation controller contains a table view controller which loads another NIB file with a table view connected to a class which is the delegate and data source delegate.
I also need to categorize the results into sections - these being
England
Scotland
Wales
N.Ireland
To get an idea of what JSON string I am using see this one.
As you can see the JSON does not cater for the sections but I am yet to implement this, so i would need to know beforehand so I do not have to amend much code later on.
OK - I am using Stig JSON parser.
Here is my ListVenuesView.h (connected to table view)
#import <UIKit/UIKit.h>
#import "SBJson.h"
#interface ListVenuesView : UITableViewController <UITableViewDelegate, UITableViewDataSource> {
IBOutlet UITableView *venueList;
NSMutableDictionary *jsonArray;
}
#property (nonatomic, retain) IBOutlet UITableView *venueList;
#property (nonatomic, retain) NSMutableDictionary *jsonArray;
#end
jsonArray is used to store the JSON data and eventually the proper array.
And here is my ListVenuesView.m (key areas in question)
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"Table View Loaded");
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
// This is where we load the JSON data
NSURL *jsonURL = [NSURL URLWithString:#"http://www.thebigfishexperience.org.uk/sources/ajax/venue-json.php?location=peterborough"];
NSString *jsonData = [[NSString alloc] initWithContentsOfURL:jsonURL];
NSLog(#"%#", jsonData);
// Convert jsonData to array
self.jsonArray = [jsonData JSONValue];
NSLog(#"%#", jsonArray);
NSLog(#"count is: %i", [self.jsonArray count]);
// Release NSString and NSURL
[jsonURL release];
[jsonData release];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [self.jsonArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
NSMutableDictionary *dict = [self.jsonArray objectAtIndex: indexPath.row];
cell.textLabel.font = [UIFont fontWithName:#"Arial" size:15.0];
cell.textLabel.text = [dict objectForKey:#"venueName"];
cell.detailTextLabel.text = [dict objectForKey:#"venueCordDist"];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
// Configure the cell...
return cell;
Also how can I use the data in the cells to go to another subview of the nav controller which gives me a back button and displays the info from the JSON string just for that particular cell that has been tapped.
I think this has something to do with it? Not sure though as this is my first app i am building! So probably expect more pleas of assistance - ha ! ;)
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Navigation logic may go here. Create and push another view controller.
/*
DetailViewController *detailViewController = [[DetailViewController alloc] initWithNibName:#"Nib name" bundle:nil];
// ...
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController release];
*/
}
On selecting a row, as mentioned by u, we are navigating to another view. Let us assume that the view controller is DetailViewController which is a sub-class of UIViewController.
In the DetailViewController.h , declare a NSDictionary object.
In DetailViewController.m, add
-(void)setVenueDict:(NSDictionary*)venueDict
{
if( _venueDict )
{
[_venueDict release];
}
_venueDict = [venueDict retain];
}
In ParentViewController, ur didSelectRow.. method should be like this.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Navigation logic may go here. Create and push another view controller.
DetailViewController *detailViewController = [[DetailViewController alloc] initWithNibName:#"Nib name" bundle:nil];
// ...
// Pass the selected object to the new view controller.
NSDictionary *dict = [self.jsonArray objectAtIndex: indexPath.row];
[detailViewController setVenueDict:dict];
detailViewController.title = [dict objectForKey:#"venueName"];
[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController release];
}
In the second view controller, u can do whatever u want with the _venueDict.
Nathan,
since you want to reuse the data parsed from the JSON feed over more than one ViewController the best way to approach this is to build an object Model so that you can pass the object for the selected row in the list to the detail ViewController.
I would also separate the JSON parsing code into a separate class and not keep it in the ViewController.
You can find classes to fetch JSON on this link.
The result from the custom code to parse the JSON feed would give back a NSDictionary with as keys the section names you mention. And the value in the NSDictionary for those keys would be an array of your custom objects that contain all the relevant data for one row (and detail screen).
Hope this helps you on your way.
jsonArray is NSMutableDictionary.
have to use
[jsonArray objectForKey:key];
//check this line
NSMutableDictionary *dict = [self.jsonArray objectAtIndex: indexPath.row];
this may help.