error while loading xib file from tableview in ios - objective-c

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.

Related

Dismiss a UISearchController View and Dissmiss UITableView to get to the root view controller

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];
}

Navigate to the right view from cell

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];

how to display various view controllers (each having its respective navigation controller) using storyboard ID

I'm working on my first app. Here's what I want to accomplish:
There will be a menu with several different options. For simplicity, assume this is comprised of UIButtons with IBAction outlets and the functionality exists to pull up the menu at any time.
Each menu button, when pressed, should display a different navigation controller's content. If the user brings up the menu and makes a different selection, the navigation controller in which he is currently operating should not be affected; the newly selected navigation chain is displayed on top of the old, and through the menu, the user can go back to the view where he left off on the previous navigation chain at any time.
visual illustration (click for higher resolution):
Please note that there are 3 different navigation controllers/chains. The root view controller (which is also the menu in this simplified version) is not part of any of them. It will not suffice to instantiate one of the navigation chains anew when it has been previously instantiated, and here's why: if the user was on screen 3 of option 2 and then selects option 1 from the menu and then selects option 2 (again) from the menu, he should be looking at screen 3 of option 2--right where he left off; the view controller he was viewing when he previously left the navigation chain should be brought back to the top.
I can make a button instantiate and present a view controller from the storyboard if there is NOT a navigation controller:
- (IBAction)buttonPressed:(id)sender {
UIViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"View 2"];
[self presentViewController:controller animated:YES completion:nil];
}
However, I can't figure out how to make those two methods work with a navigation controller involved. Moreover, I'm not sure those two methods are the right choice, because I won't always want to instantiate a new view controller: when a menu button is pressed, a check should be performed to see if the view (navigation?) controller with the corresponding identifier has already been instantiated. If so, it should simply be made the top view controller.
In summary, here are my questions:
1) How should I instantiate and display a view controller that is embedded in a navigation controller, preferably using a storyboard ID? Do you use the storyboard ID of the navigation controller or of the view controller?
2) How should I check whether an instance already exists? Again, should I check for an extant navigation controller or for a view controller, and what's the best method to do so?
3) If the selected navigation chain has already been instantiated and is in the stack of view controllers somewhere, what is the best method for bringing it to the top?
Thank you!!
side note -- it would be nice to know how to paste code snippets with indentation and color formatting preserved :)
As Rob has suggested, a tab bar controller would make a good organising principle for your design.
Add a UITabBarController to your storyboard, give it a storyboard iD. Assign each of your three sets of viewControllers ( with their respective navController) to a tab item in the tabBarController.
UITabBarController
|--> UINavigationController --> VC1 ---> VC2 -->
|--> UINavigationController --> VC1 ---> VC2 -->
|--> UINavigationController --> VC1 ---> VC2 -->
In you app delegate make a strong property to hold your tab bar controller's pointer. As the tab bar controller keeps pointers to all of it's tab items, this will take care of state for each of your sets of viewControllers. You won't have to keep separate pointers for any of them, and you can get references to them via the tabBarController's viewControllers property.
#property (strong, nonatomic) UITabBarController* tabVC;
Initialise it on startup
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UIStoryboard storyBoard =
[UIStoryboard storyboardWithName:#"MainStoryboard_iPhone" bundle:nil];
self.tabVC = [storyBoard instantiateViewControllerWithIdentifier:#"tabVC"];
//hide the tab bar
for (UINavigationController* navController in self.tabVC.viewControllers)
[navController.viewControllers[0] setHidesBottomBarWhenPushed:YES];
return YES;
}
An alternative way to hide the tab bar is to check the "Hides bottom bar on push" box in the Attributes Inspector for each of the (initial) viewControllers. You don't have to do this for subsequent viewControllers, just the first one that will be seen in that tab item.
Then when you need to navigate to one of your navController groups…
- (IBAction)openTab:(UIButton*)sender {
AppDelegate* appDelegate =
(AppDelegate*)[[UIApplication sharedApplication] delegate];
if ([sender.titleLabel.text isEqualToString: #"Option 1"]) {
appDelegate.tabVC.selectedIndex = 0;
}else if ([sender.titleLabel.text isEqualToString: #"Option 2"]){
appDelegate.tabVC.selectedIndex = 1;
}else if ([sender.titleLabel.text isEqualToString: #"Option 3"]){
appDelegate.tabVC.selectedIndex = 2;
}
[self presentViewController:appDelegate.tabVC
animated:YES completion:nil];
}
(this example uses presentViewController, your app design may navigate this in other ways…)
update
If you want to do this without a tab bar controller, you can instantiate an array holding pointers to each of your nav controllers instead:
UINavigationController* ncA =
[storyboard instantiateViewControllerWithIdentifier:#"NCA"];
UINavigationController* ncB =
[storyboard instantiateViewControllerWithIdentifier:#"NCB"];
UINavigationController* ncC =
[storyboard instantiateViewControllerWithIdentifier:#"NCC"];
self.ncArray = #[ncA,ncB,ncC];
Which has the benefit of not having a tab bar to hide…
Then your selection looks like…
- (IBAction)openNav:(UIButton*)sender {
AppDelegate* appDelegate =
(AppDelegate*)[[UIApplication sharedApplication] delegate];
int idx = 0;
if ([sender.titleLabel.text isEqualToString: #"option 1"]) {
idx = 0;
}else if ([sender.titleLabel.text isEqualToString: #"option 2"]){
idx = 1;
}else if ([sender.titleLabel.text isEqualToString: #"option 3"]){
idx = 2;
}
[self presentViewController:appDelegate.ncArray[idx]
animated:YES completion:nil];
}
1 / You can instantiate a viewController in your viewDidLoad method of your main viewController, so it will be instantiate 1 time only.
Now if you want display your controller, you would better push it :
- (IBAction)buttonPressed:(id)sender {
// Declare your controller in your .h file and do :
controller = [self.storyboard instantiateViewControllerWithIdentifier:#"View 2"];
// Note you can move this line in the viewDidLoad method to be called only 1 time
// Then do not use :
// [self presentViewController:controller animated:YES completion:nil];
// Better to use :
[self.navigationController pushViewController:controller animated:YES];
}
2 / I'm not sure, but if you want to check if an instance already exist just check :
if (controller) {
// Some stuff here
} // I think this checks if controller is initiated.
3 / I know it's not a good advice but I would tell you to not worry about checking if your controller already exist, because I think it's easier to access your viewController by using the 2 lines again :
controller = [self.storyboard instantiateViewControllerWithIdentifier:#"View 2"];
[self.navigationController pushViewController:controller animated:YES];
4 / I'm not sure if colors can be used here because of a specific style sheets.
I'm not sure to really have the good answer to your question but I hope this will help you.

pushViewController is not pushing

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.

Unable to display the detail view on selecting a row in TableView with a UITabBar

I am using a Navigation based application.The third view in my flow has a UITabbar added.On clicking one of the tabs a TableView is displayed.On selecting a row of this TableView I wish to display another view.
My code works fine to the point of displaying the different views on clicking the tabs.When I select a row of the TableView nothing is displayed.I use a plist to populate the tableView. I added the following code
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
PropertyRegistration *dvController = [[PropertyRegistration alloc] initWithNibName:#"PropertyRegistration" bundle:[NSBundle mainBundle]];
//dvController.selectedCountry = selectedCountry;
[self.navigationController pushViewController:dvController animated:YES];
[dvController release];
dvController = nil;
}
Can someone help?
I assume the third view controller is a UITabBarController which is working fine. But your root controllers in each tab, are you sure that they are UINavigationControllers? They (or at least the one containing your table view) need to be.
If your third view controller is not a UITabBarController, I'd recommend that you change it to be so. Then your structure would be something like:
UINavigationController: pushes through two UIViewControllers, then a UITabBarController (your third).
UITabBarController contains some view controllers, one or more of which is a UINavigationController. This navigation controller has a UIViewController as it's root view controller, and has other controllers pushed onto it.