Programmatically Push VC on Table Row Tap - ios

I am attempting to do a onRowTap method without using a storyboard segue to push to a new View Controller, however when tapped it only displays information from the first item of the indexPath no matter which row is tapped. Here is my code:
- (void)tableView:(UITableView *)theTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
NSInteger row = [[self tableView].indexPathForSelectedRow row];
NSDictionary *insta = [self.instaPics objectAtIndex:row];
UIStoryboard* sb = [UIStoryboard storyboardWithName:#"Main"
bundle:nil];
InstaPicDetailViewController* vc = [sb instantiateViewControllerWithIdentifier:#"InstagramDetail"];
vc.detailItem = insta;
[self.navigationController pushViewController:vc animated:YES];
}

Move your deslectRowAtIndexPath message call below the assignment of your row variable:
NSInteger row = [[self tableView].indexPathForSelectedRow row];
[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];

Related

deselecting UITableViewCell

I'm calling a view controller from a table view. When I return back the caller view the table cell that I pressed before stays selected so that I couldn't select it again before selecting another cell.
I've added deselectRowAtIndexPath method like below but it didn't worked.
- (void) tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *ctrl = [storyboard instantiateViewControllerWithIdentifier:#"node"];
self.navigationController.navigationBarHidden = NO;
self.navigationController.navigationItem.hidesBackButton = NO;
[self.navigationController pushViewController:ctrl animated:YES];
}
didDeselectRowAtIndexPath is only called AFTER your row has already been deselected, so your call to deselectRowAtIndexPath is useless. Simply place this in your didSelectRowAtIndexPath to deselect it after tapping on it:
[tableView deselectRowAtIndexPath:indexPath animated:YES];
If you are using UITableViewController there is a property for that. You can set it in you -viewDidLoad method of your UITableViewController subclass:
self.clearsSelectionOnViewWillAppear = YES;
Otherwise you have to do it manually. Just deselect it in -viewWillAppear:
- (void)viewWillAppear:(BOOL)animated {
[self.tableView deselectRowAtIndexPath:self.tableView.indexPathForSelectedRow];
}
The method you have shown is not necessary for this.
You are committing an error on the delegate method. When you select a row in a tableView, is called:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
So your code should be in this method:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *ctrl = [storyboard instantiateViewControllerWithIdentifier:#"node"];
self.navigationController.navigationBarHidden = NO;
self.navigationController.navigationItem.hidesBackButton = NO;
[self.navigationController pushViewController:ctrl animated:YES];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
So now that you call deselectRowAtIndexPath is called also:
- (void) tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath;
But in your case, you don't need to implement something in this method.

IOS storyboard - show different views on selection of table cells

i am new to ios programming. I have multiple view controllers. i am showing the tableView Controller first and there is a navigation controller before it .. i want to show the specific view controller depending on the cell selected.. i have set tableView Controller to dynamic and prototype Cell to 1
and i have segue which connected from table to my one of view controller name APP1ViewController i have another two controllers name APP2 and APP3 .. how can i connect them so that on the specific cell specific view controller loads.
here is the code of displaying cells .. at the moment there is one section and three rows in my table
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"AppCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
switch (indexPath.row)
{
case 0:
cell.textLabel.text = #"APP 1 ";
cell.detailTextLabel.text = #"Detail of App 1...";
break;
case 1:
cell.textLabel.text = #"App2";
cell.detailTextLabel.text = #"Detail of App 2 app...";
break;
case 2:
cell.textLabel.text = #"App3";
cell.detailTextLabel.text =
#"Detail of App 3...";
break;
default:
cell.textLabel.text = #"Unkown";
cell.detailTextLabel.text = #"Unknown";
break;
}
return cell;
}
Create your three segues from the controller that has the table rather than from the table or the cell itself. Give each segue a unique identifier. In tableView:didSelectRowAtIndexPath:, call the table view controller's performSegueWithIdentifier:sender: method and select the identifier that matches the chosen row.
Try this,
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"your storyboard" bundle:nil];
UIViewController *viewController = nil;
switch (indexPath.row) {
case 0:
viewController = [storyboard instantiateViewControllerWithIdentifier:#"viewController1"];
break;
case 1:
viewController = [storyboard instantiateViewControllerWithIdentifier:#"viewController2"];
break;
case 2:
viewController = [storyboard instantiateViewControllerWithIdentifier:#"viewController3"];
break;
default:
viewController = [storyboard instantiateViewControllerWithIdentifier:#"viewController4"];
break;
}
[[self navigationController] pushViewController:viewController animated:YES];
}
Implement One of Tablview's delegate method
tableView:didSelectRowAtIndexPath:
and on the above delegate method you can fetch particular view controller form your storyboard and instantiate and push to your navigation's controller as follows
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"your storyboard" bundle:nil];
UIViewController *viewController = [storyboard instantiateViewControllerWithIdentifier:#"Your Storyboard's identifier that you want to push"];
[[self navigationController] pushViewController:viewController animated:YES];

how to make pushViewController: work in the following case?

I have a Navigation Controller embedded in a RootViewController. The elements present inside the RootViewController are a segmented control and a UIView. As the different segments are selected, the UIView displays a corresponding ViewController.
Now each of the ViewController being displayed in the UIView is a UITableViewController.
I need to display the table values as per the segment selections. And also if any of the row of the table is selected, it has to move to a newer ViewController with the detailed view.
I am able to display the UITableViewControllers as per the segment change. However, when i click on the row of the table, the newer ViewController that comes up is blank (Black Screen) even though I have created the particular ViewController in the Storyboard and set up an identifier as well.
Code for the Segmented Control change in ViewController.m
- (void)segmentedControlChangedValue:(UISegmentedControl*)segmentedControl {
int selIndex = segmentedControl.selectedIndex;
if (selIndex == 0)
{
aTable = [[aTableViewController alloc] init];
aTable.view.frame = self.myView.bounds;
[self.myView addSubview:aTable.view];
[self addChildViewController:aTable];
}
if (selIndex == 1)
{
bTable = [[bTableViewController alloc] init];
bTable.view.frame = self.myView.bounds;
[self.myView addSubview:bTable.view];
[self addChildViewController:bTable];
}
if (selIndex == 2)
{
//NSLog (#"Well you selected a 3rd option");
}}
Code for the didSelectRowAtIndexPath:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[super tableView:tableView didSelectRowAtIndexPath:indexPath];
newDetailController* newController = [self.storyboard instantiateViewControllerWithIdentifier:#"Detail"];
newController = [[newDetailController alloc] init];
[[self navigationController] pushViewController:newController animated:YES];}
The pushViewController pushes an empty view for me even though I have specified the ViewController to use in the Storyboard design and also using an identifier.
Please help me in understanding what I must do to rectify this error.
UPDATE - The above problem has been resolved.
The problem I face now is being unable to access the data in the newViewController.
I pass the data to the newViewController as follows:
Create a class named newClass which contains all the elements I want to pass across.
Create a NSMutableArray "newObjects" in the firstViewController.
Create each newClass object at this method.
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object
{
static NSString *CellIdentifier = #"Cell";
customBigTableCell *cell = (customBigTableCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[customBigTableCell alloc] init];
}
cell.name.text = [object objectForKey:#"objName"];
newClass* newObj = [[newClass alloc] init];
newObj.objName = cell.name.text;
[newObjects addObject:newObj];
return cell;
}
Pls pardon me .. for the indenting with the code block is messed up...
Also the PFObject is cos i use Parse for database.
Add the created object to the newObjects array.
In the - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath method, this is the code
(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[super tableView:tableView didSelectRowAtIndexPath:indexPath];
UIStoryboard* storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:[NSBundle mainBundle]];
newDetailController* newController = [storyboard instantiateViewControllerWithIdentifier:#"UpcomingDetail"];
obj = [[newClass alloc] init];
NSIndexPath* path = [self.tableView indexPathForSelectedRow];
obj = [newObjects objectAtIndex:path.row];
NSLog(#"Row selected is %ld", (long)path.row); //this returns the correct row selected
NSLog(#"Movie selected is %#", [[newObjects objectAtIndex:path.row] objName]);//however this is not the right one as per the cellForRowAtIndexPath method.
[newController setNewObj:obj];
[[self navigationController] pushViewController:newController animated:YES];
}
When I run this code, the row is selected correctly. However I dont get the corresponding row in the database. The array gets stored with redundant data.
You need to get rid of that middle line:
newController = [[newDetailController alloc] init];
That just redefines newController (as an empty controller with no view set up), which you defined in the first line.

iOS carrying data over when pushing a new view

I have an app that is parses XML and stores in an NSObject ("Call"). I then display the table in a data like so:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
Call *currentCall = [[xmlParser calls] objectAtIndex:indexPath.row];
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell==nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = currentCall.call_name;
cell.detailTextLabel.text = currentCall.location;
cell.accessoryType = UIButtonTypeRoundedRect;
return cell;
}
My question is when I am pushing to the detail view controller, how do I set up the didSelectRowAtIndexPAth method to be able to access all the objects properties? I use to use this way, which works, but I am sure it is not the most efficient way. Thanks for the help.
Old way:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"indexPath = %d", indexPath.row);
Call *currentCall = [[xmlParser calls] objectAtIndex:indexPath.row / 2];
self.currentCallTypeDetail = currentCall.currentCallType;
self.unitsDetail = currentCall.units;
self.locationDetail = currentCall.location;
self.countyDetail = currentCall.county;
self.stationDetail = currentCall.station;
self.fullcallnumberDetail = currentCall.fullcallnumber;
self.latitude = currentCall.latitude;
self.longitude = currentCall.longitude;
self.callTypeDetail = currentCall.callType;
self.callNumberDetail = currentCall.callnumber;
self.timeDetail = currentCall.time;
[tableView deselectRowAtIndexPath:indexPath animated:YES];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle: nil];
CallTypeDetailController *vc = [storyboard instantiateViewControllerWithIdentifier:#"calltypedetail"];
[vc setCurrentCallTypeDetail:self.currentCallTypeDetail];
[vc setUnitsDetail:self.unitsDetail];
[vc setLocationDetail:self.locationDetail];
[vc setCountyDetail:self.countyDetail];
[vc setStationDetail:self.stationDetail];
[vc setFullcallnumberDetail:self.fullcallnumberDetail];
[vc setCallTypeDetail:self.callTypeDetail];
[vc setCallNumberDetail:self.callNumberDetail];
[vc setTimeDetail:self.timeDetail];
[vc setLatitude:self.latitude];
[vc setLongitude:self.longitude];
[self.navigationController pushViewController:vc animated:YES];
NSLog(#"Selected Call = %#", self.currentCallTypeDetail);
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"indexPath = %d", indexPath.row);
Call *currentCall = [[xmlParser calls] objectAtIndex:indexPath.row / 2];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle: nil];
CallTypeDetailController *vc = [storyboard instantiateViewControllerWithIdentifier:#"calltypedetail"];
[vc setCurrentCall:currentCall];
[self.navigationController pushViewController:vc animated:YES];
NSLog(#"Selected Call = %#", self.currentCallTypeDetail);
}

Iphone tableview

I am using below code for getting index number of the row. I want to get the Text of row. Please tell me, what modifications are required to get the text from each row.
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *__strong)indexPath{
DetailViewController *detail = [self.storyboard instantiateViewControllerWithIdentifier:#"Detail"];
[self.navigationController pushViewController:detail animated:YES];
detail.rowNum.text = [NSString stringWithFormat:#"Row: %d", (indexPath.row) ];
}
thanx in advance :)
You can get cell with all its properties this way:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *__strong)indexPath{
DetailViewController *detail = [self.storyboard instantiateViewControllerWithIdentifier:#"Detail"];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
detail.rowNum.text = [NSString stringWithFormat:#"Row: %d", (indexPath.row) ];
detail.someLabel.text = cell.textLabel.text;
[self.navigationController pushViewController:detail animated:YES];
}
Is this what you want? Text from selected cell?
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *__strong)indexPath{
DetailViewController *detail = [self.storyboard instantiateViewControllerWithIdentifier:#"Detail"];
[self.navigationController pushViewController:detail animated:YES];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSString *cellText = cell.textLabel.text;
detail.rowNum.text = cellText;
}
Update ur code as above.

Resources