I have this code to navigate from my tableview to another tableview. But it doesnt navigate to the right tableview. It seems that it creates another view that it navigates to and not the one on my storyboard that I want to go to.
Is this because I create an object?
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *) indexPath
{
ValjKupongViewController *vk = [[ValjKupongViewController alloc]init];
[self.navigationController pushViewController:vk animated:YES];
}
How can I write this the right way so that I navigate to my view in storyboard that have the class ValjKupongViewController?
Very grateful for help!
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *) indexPath
{
[self performSegueWithIdentifier: #"My Custom Segue" sender: self];
}
In your StoryBoard
Step 1 Ctrl and Drag the mouse from the
View Controller on the left to the View Controller on the right.
View Controller on the left = The View Controller you are transitioning FROM.
View Controller on the right = The View Controller you are transitioning TO.
Step 2 Select push as the type of Segue
Step 3 Now your View Controllers will have the Segue between them (as seen below)
Step 4 You need to name the Segue to be able to identify it.Click on the Segue, then go to the attributes inspector and set the Identifier. (In the example it is set to My Custom Segue.
Make sure this is the same as in the code above.
i.e. [self performSegueWithIdentifier: #"My Custom Segue" sender: self];
Is this because I create an object?
Yes you are allocating and initialising a ValjKupongViewController object each time didSelectRowAtIndexPath is called. With this line of code
ValjKupongViewController *vk = [[ValjKupongViewController alloc]init];
You then transition to it with this line
[self.navigationController pushViewController:vk animated:YES];
Related
Context: I am creating an IOS application in Objective C with the ArcGIS Runtime SDK. My root view controller is a map. I have the option to create spatial bookmarks and view them in a table view that is pushed over the view. I have a UISearchController on the table view to be able to filter out the bookmarks. If you select a bookmark without searching, you are automatically panned to that location. This is done by popping all view controllers, and loading the root view controller with a flag for the bookmark variable to set as the starting extent.
I would like this same functionality with the searchController table view.
However, I am either unable to dismiss the searchController and the bookmark is zoomed to, or the search controller is dismissed, and the user is brought back to the initial table view.
What I have so far:
In the didSelectRow method on the searchController TableView:
(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
//Accept the spatial envelope and save it to the shared variable to be passed to main view controller
//Now dismiss the searchController and call method to zoom to bookmark
[self.navigationController dismissViewControllerAnimated:NO completion:^{
//reference to shared instance method
[[BookmarksTableViewController sharedBookmark] zoomToBookmark];
}];
In BookmarksTableViewController.m
-(void)zoomToBookmark{
UIViewController *myController = [self.storyboard instantiateViewControllerWithIdentifier:#"viewController"];
[self.navigationController pushViewController: myController animated:YES];
//clear the navigation stack
self.navigationController.viewControllers = [[NSArray alloc] initWithObjects:myController, nil];
}
To me it seems like this should work, but all that happens is the UISearchController is dismissed, then the table view is not dismissed, and I am back where I was before I entered search text.
Any thoughts on a better way to dismiss the UISearchController or how to get back to my root view controller?
Hope you mean to this answer
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self dismissViewControllerAnimated:NO completion:nil];
}
i am trying to make an app in which i use tableview.
I am populating the tableview and i am able to display data in the table. Now what i am trying to do is when i click a specific cell in the tableview i want to load a particular xib file in different folder. For all other cell i want to load second tableview. i am using a storyboard.
i am using
(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([((UITableViewCell *)sender).textLabel.text isEqualToString:#"ABCD"]) {
ABCD *abcdViewController = [[ABCD alloc] initWithNibName:#"ABCD" bundle:nil];
// Push the view controller.
[self.navigationController pushViewController:ABCDViewController animated:YES];
}
// Pass the selected object to the new view controller.
NSLog(#"%#", ((UITableViewCell *)sender).textLabel.text);
MethodsViewController *methodsViewController = segue.destinationViewController;
NSString *rowTitle = ((UITableViewCell *)sender).textLabel.text;
NSDictionary *selected = [[self methodsDict] objectForKey:rowTitle];
methodsViewController.rows = [selected objectForKey:#"rows"];
methodsViewController.methodsDict = [selected objectForKey:#"methodsDict"];
}
This is the code i am using. i made this code after searching the internet.
but the problem is
but when i build and run this the first tableview is shown and when i click on the ABCD cell the xib loads but the navigation bar is covering the upper portion of the xib file and when i click on the back button in the navigation bar it takes me to the black blank page and shows a error
nested push animation can result in corrupted navigation bar
Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted.
and the app stops
I dont know what i am doing wrong i am new to ios
I hope you understand my problem
Thanks in advance
You have at least three possible approaches to what you are trying to do.
The easiest one is using shouldPerformSegueWithIdentifier: to control exactly when segueing as specified in IB and when pushing your ABCD view controller instead:
- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender{
if ([((UITableViewCell *)sender).textLabel.text isEqualToString:#"ABCD"]) {
ABCD *abcdViewController = [[ABCD alloc] initWithNibName:#"ABCD" bundle:nil];
// Push the view controller.
[self.navigationController pushViewController:ABCDViewController animated:YES];
return NO;
}
return YES;
}
This should work pretty easily for you, since it is similar to what you have been trying to do with prepareForSegue:. The fault with your current approach using prepareForSegue: is that you are both pushing your ABCD controller and doing the segue. shouldPerformSegueWithIdentifier: allows you to cancel the segue, so to say, when you are going to push manually.
Another approach would be using manual segues:
you can create a manual segue in IB by dragging from the view controller (as opposed to dragging from the prototype table cell); you can create multiple named segues;
in your table view delegate you override tableView:didSelectRowAtIndexPath: so that it calls performSegueWithIdentifier::
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *identifierOfSegueToCall;
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:nowIndex];
if ([cell.textLabel.text isEqualToString:#"ABCD"]) {
identifierOfSegueToCall = #"ABCDSegueIdentifier";
} else {
identifierOfSegueToCall = #"XYWZCellSegueIdentifier";
}
[self performSegueWithIdentifier:identifierOfSegueToCall sender:self];
}
Finally, a third approach would be defining two different cell prototypes for your table view and segueing from each prototype cell into the appropriate view controller. This is similar to what you have already done for setting up your current segue, only you should add a new prototype cell and define a specific segue from it.
I've spent hours and I cant figure this out. I have a detail view controller (UITableView) which is launched here:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
EventLocationDetailController *newDetailViewController = [[EventLocationDetailController alloc] initWithNibName:#"EventLocationDetailController" bundle:nil];
self.eventDetailController = newDetailViewController;
[self.navigationController pushViewController:self.eventDetailController animated:YES];
[newDetailViewController release];
}
In the detail view controller there is a button method which calls the below method to display a slide-in-slide-out animation confirming the users choice:
-(void)confirmLastActionWithMessage:(NSString *)message {
ConfirmActionViewController *newConfirmActionViewController = [[ConfirmActionViewController alloc] initWithNibName:#"ConfirmActionViewController" bundle:nil];
self.confirmActionViewController = newConfirmActionViewController;
[newConfirmActionViewController release];
[[self.view superview] addSubview:self.confirmActionViewController.view];
}
Protocol method called by the ConfirmActionViewController indicating that the animation is finished.
-(void)didFinishConfirmDisplay:(UIView *)viewToRemoveFromSuperview {
[viewToRemoveFromSuperview removeFromSuperview];
}
This works perfect the first time I press the button. If I pop the detail controller and push it back on to the stack and press the button again, nothing happens and the detail controller's superview is nil every time I invoke the method after that. Superview is not nil in the viewWillAppear method for the detail view, only when It gets to the confirmLastActionWithMessage method. No other user interaction happens in between. How do I get the superview back? I have a similar code that works without animation.
I've also noticed that the detail view controller hasn't called dealloc when popped off the stack. Not sure where the problem is.
Thanks.
EDIT 1
OK. I replaced the addSubview line with this one:
[self.view insertSubview:self.confirmActionViewController.view atIndex:0];
and the animation view appeared underneath one of the table cells. Could one of the table cells steal the superview?
Well I don't really understand why you should add the subview to the superview. Why not add it just to self.view
I may not be able to explain why there is no superview but try either adding the controller view to self.view or
[[[[UIApplication sharedApplication] delegate] window] addSubview:yourview];
This will render the view on top of everything.
I was using initWithNibName to push the cells to detail views but I want to use single storyboard rather than having numerous nib files. The below code is supposed to push the view to subcategoriesViewController when the cell is clicked. the cells are dynamic from json data.
Its not giving any errors. Do you think its an issue with navigation control? Just to test, I added a button on this view and it works; when I click it, it does push to next view.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSDictionary *dict = [rows objectAtIndex: indexPath.row];
subcategoriesViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"subcategoriesViewController"];
controller.CATNAME = [dict objectForKey:#"C_NAME"];
controller.CATNUMBER = [dict objectForKey:#"CAT_ID"];
[self.navigationController pushViewController:controller animated:YES];
// [controller release];
}
Okay I think I have found the cause; but don't know how to fix it.
The tableview in this controller is actually a subview of a viewController. I duplicated these files and created a new view which is a TableViewController. This code, when used in the TableViewController does the job, but it doesn't do it when used in a controller where the tableview is a subview of a ViewController.
I want the table to be a subview because I want to put an image above the table. So, I think the problem here is this line:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
It does not reference the table in the view. Can anyone tell me how to modify this so it would reference the table within the view?
If didSelectRow... is not being called then your view controller is probably not set as the delegate of your table view.
This is set up for you automatically when using a UITableViewController but you have to explicitly do it when using a standard view controller.
An answer to your problem is often that self.navigationController is in fact nil because there is no navigation controller for your view. You perhaps have to get a pointer to the navigation controller of your projet and push your view on it.
I have a main UITableView, when cell is pressed it goes to another UITableView and when a cell is pressed there it goes to a DetailView of that cell.
I want the middle UITableView to behave differently depending on if the detailView got popped or the UITableView itself got pushed. If the view got pushed on from the main table I want to scroll to the top, if it is shown after a DetailView got popped I want it to stay at the same position.
Any suggestions?
you could call a scrollToTop method on the DetailViewController after you have pushed it to the navigationController.
Something like that:
if (!detailViewController) {
detailViewController = [[DetailViewController alloc] initWithNibName:nil bundle:nil];
}
[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController scrollToTop];
// or use the tableView directly:
// [detailViewController.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:YES];
In your Middle View Controller, examine which view is next-to-display directly from the UINavigationController stack:
- (void)viewWillDisappear:(BOOL)animated
{
if ([self.navigationController.topViewController isEqual:(UITableViewController *)tvcDetailView]) {
// Detail view has been pushed onto the UINavigationController stack
}
else {
// Middle view has been popped from the UINavigationController stack
}
}
Create a BOOL #property on your middle UIViewController property called wasPushed or something similar, and when you initialise it from UIViewController 1, set the property on the new instance, push it onto the nav stack and you can then use your property in your middle view controller's loadView, viewDidLoad, viewWill/DidAppear methods.
As soon as you've used it, set it back to FALSE or NO (or whatever) and when you end up coming back to it due to popping off your 3rd view controller you'll have it as FALSE/NO in your loadView, viewDidLoad etc.. methods.