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.
Related
In a table view, did select row at index path not second time when select row. Here is my code
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (!self.thirdvc) {
self.thirdvc=[[UIStoryboard storyboardWithName:#"Main" bundle:nil]instantiateViewControllerWithIdentifier:#"thirdview"];
}
[self.navigationController pushViewController:thirdvc animated:YES]; // this is right way .
}
make sure that your tableview is allow only single selection. From your storyboard select your tableview, from attribute inspector select single selection for option selection. or you can set it by code like,
yourTableView.allowsMultipleSelection = NO;
Because after you select the first time, it is marked as selected, so the second time you press, it will become unselected. so just deselect the row:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
if (!self.thirdvc) {
self.thirdvc=[[UIStoryboard storyboardWithName:#"Main" bundle:nil]instantiateViewControllerWithIdentifier:#"thirdview"];
}
[self.navigationController pushViewController:thirdvc animated:YES];
}
You have declared thirdvc as the instance variable of the class and in didSelectRowAtIndexpath method, you are check if it's nil, then instantiate it and push it to thirdvc. So in second time thirdvc is not nil, so it's not working. To make it work change your code as:
(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (!self.thirdvc) {
self.thirdvc=[[UIStoryboard storyboardWithName:#"Main" bundle:nil]instantiateViewControllerWithIdentifier:#"thirdview"];
// [self.navigationController pushViewController:thirdvc animated:YES];
}
[self.navigationController pushViewController:thirdvc animated:YES];
}
Replace code with this one:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
self.thirdvc = nil;
if (!self.thirdvc) {
self.thirdvc=[[UIStoryboard storyboardWithName:#"Main" bundle:nil]instantiateViewControllerWithIdentifier:#"thirdview"];
}
[self.navigationController pushViewController:thirdvc animated:YES]; // this is right way .
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"cell taped");
NSDictionary *temDict1 =[objects objectAtIndex:indexPath.row];
I have a dictionary on Viewcontroller A .I am passing it on viewcontroller B.On ViewController A it shows data on the dictionary of viewcontroller B.But ,In Viewcontroller it doesnt show any data in it?
ViewController A:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
TableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
if (cell== nil) {
cell = [[TableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
}
if(_List.count>0) {
[cell setupCell:[_List objectAtIndex:indexPath.row]];
ViewControllerB *vc=[[ViewController alloc]init];
vc.userIdInfo=[_List objectAtIndex:indexPath.row];
}
return cell;
}
ViewController B:
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"_userIdInfo %#",userIdInfo);
if([userIdInfo valueForKey:#"UserID"]) {
[self fetchDataFromServer:getdetail];
}
}
This NSLog(#"_userIdInfo %#",userIdInfo) prints null. while vc.userIdInfo prints dictionary
{
Count = 3;
UserID = "6gdab241-j176-1121-lde2-as8d21f62231";
UserName = "abc#gmail.com";
}
In objective C, cellForRowAtIndexPath methods is used for showing the data.
As per code, you are intiallising the ViewController B in cellForRowAtIndexPath.
it will allocate ViewController B multiple time which lead to memory consumptions.
I would suggest you to initialise in ViewDidLoad of ViewController A.
For Passing the data from A to B, you need to Use didSelectRowAtIndexPath method of UITableViewDelegate.
Example:
ViewController A:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
TableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
if (cell== nil) {
cell = [[TableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
}
if(_List.count>0) {
//Use to show data
cell.textLabel.text = [NSString stringWithFormate:#"%#",[_List objectAtIndex:indexPath.row]]];
// [cell setupCell:[_List objectAtIndex:indexPath.row]];
// ViewControllerB *vc=[[ViewController alloc]init];
// vc.userIdInfo=[_List objectAtIndex:indexPath.row];
}
return cell;
}
ViweController B
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// 1st Type
ViewControllerB *vc=[[ViewController alloc]init];
vc.userIdInfo=[_List objectAtIndex:indexPath.row];
[self.navigartionController pushViewController:aVC animated:YES];
}
You need to do ViewController B initialization in DID select method like below.
Don't initialize it in cellForRowAtIndexPath.
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// 1st Type
ViewControllerB *vc=[[ViewController alloc]init];
vc.userIdInfo=[_List objectAtIndex:indexPath.row];
[self.navigartionController pushViewController:aVC animated:YES];
//2nd Type
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
ViewControllerB *aVC = [storyboard instantiateViewControllerWithIdentifier:#"ViewController"];
aVC.userInfo = <set your data>;
[self.navigartionController pushViewController:aVC animated:YES];
}
Hope this will helps.
The code
ViewControllerB *vc=[[ViewController alloc]init];
vc.userIdInfo=[_List objectAtIndex:indexPath.row];
only creates ViewController; it doesn't present it anywhere. moreover, the instance vc will be deallocated right after you leave the scope of
if(_List.count>0){}
your method
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"_userIdInfo %#",userIdInfo);
if([userIdInfo valueForKey:#"UserID"])
{
[self fetchDataFromServer:getdetail];
}
}
will never be called, because your view will never load.
I assume, that what you really want is to present your vc instance with navigationController instance, or from current viewController
[self.navigationController presentViewController: vc animated: YES completion: nil];
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];
The code for Tableview :
-(void)tableView:(UITableView *)tableView didselectRowAtIndexPath:(NSIndexPath *)indexPath{
ViewControllerDisplayMsg *detail = [self.storyboard instantiateViewControllerWithIdentifier:#"viewController3"];
cellvalue=[array objectAtIndex:indexPath.row];
detail.DisplayMsgString = cellvalue;
[self.navigationController pushViewController:detail animated:YES];
}
Code in viewController3 :
- (void)viewDidLoad
{
[super viewDidLoad];
self.DisplayMsgLabel.text= self.DisplayMsgString;
}
The code above is not passing data its blank when the viewcontroller3 is opened.Why is the data not passing .What code is missing ?
Please help me out.Really appreciate the help.
Thanks in Advance.
You have used
-(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath{
}
It is
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
}
I hope you have typed it by mistake please share your result if it is something else than this
Since I had segue from the story board The didselect method was not being called so -
(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// test segue.identifier if needed
ViewControllerDisplayMsg *viewController = segue.destinationViewController;
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
// set properties of viewController based on selection indexPath
cellvalue=[array objectAtIndex:indexPath.row];
NSLog(#"str : %#",cellvalue);
viewController.DisplayMsgtext = cellvalue;
}
This worked perfectly fine.I have to check it if this is right way of implementing but otherwise its working fine now.
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.