How to navigate to next view controller in iPhone - uiviewcontroller

I am newbie to iOS development.I have two view controllers in my app. I am trying to navigate from first view controller to second view controller in my app.
SecondView *ss=[[SecondView alloc] initWithNibName:#"Second Page" bundle:nil];
[self.navigationController pushViewController:ss animated:YES];
I found this code in "Stack overflow" but it won't work.

You are getting this error because you are likely trying to go from one VC to another using Navigator controller code (push) and you likely do not have a navigation controller setup in code or Interface Builder.
You can present/dismiss VCs without using Navigation Controller though and I recommend you start with this.
Notice the terminology: push/pop is used for VCs on the Navigation Controller stack, present/dismiss is for VCs on other VCs (not on a Navigation Controller stack).
There are a couple of way to present a VC on "top" of another VC and it depends on whether that VC exists on your SB as well:
1- If the VC does not exist in your IB and you are just creating and presenting the VC programmatically, you can do:
MyUIViewControllerSubclass *myLittleSubclass=[[MyUIViewControllerSubclass alloc]init];
myLittleSubclass.view.frame=self.view.frame; //this is for example only
[self presentViewController:myLittleSubclass animated:YES completion:nil];
With the above, you obviously would have to add the MyUIViewControllerSubclass Objective C class first to your project (using add files) and import it to whichever class you are putting the above code.
Later to dismiss it, you can use the following code from the MyUIViewControllerSubclass class itself.
[self.parentViewController dismissViewControllerAnimated:YES completion:nil];
2- If you have already added the MyUIViewControllerSubclass Objective C class to your project (using add files) but you intend to use the IB to design it and you have added the VC in the IB and changed its class in the IB to MyUIViewControllerSubclass, you can then use this code:
mySubclass *myLittleSubclass=[self.storyboard instantiateViewControllerWithIdentifier:#"theVC"];
[self presentViewController:myLittleSubclass animated:YES completion:nil];
You can dismiss same as above. Make sure that you click on the VC in SB and in the identity inspector, put the SB ID as "theVC" and check "Use SB ID".
Hope this helps.

Make sure that you have nib name with Second Page. Your class name is SecondView and nib(xib) name is Second Page then only it will navigate.

Related

How to create a container/child viewcontroller relationship in interface builder

To create from code a parent/child relationship between 2 view controllers basically it's just matter of doing something like:
[self addChildViewController:childViewController];
[self.view addSubview:childViewController.view];
where self is the parent view controller.
But, what if I want to create the same relationship completely from Interface Builder?
Or in other words: is there a way to re-create the behavior of the method addChildViewController using Interface Builder?
I didn't find a lot of documentation about that, here is an old unresolved post about the topic: https://devforums.apple.com/message/455758#455758
Without properly setting up the addChildViewController relationship, none of the rotation methods are forwarded to my child view controller, here where my question come from.
This is what I've done in IB:
drag and dropped a "View Controller" object from the "Object Library" panel into the "Objects" panel
in the identity inspector I've changed its class to my UIViewController subclass ("Items View Controller")
connected the view outlet to the controller
connected all the other required outlets to the controller (List name, Table View)
The first "View" object in the picture is the view of my parent view controller, instead the highlighted "View" is the view of the child view controller ("Item View Controller").
The container controller also retain its child instance through an additional IBOutlet:
#property (nonatomic, strong) IBOutlet ItemsViewController *itemsViewController;
Thanks
Update 1: If I manually set the parent/child relationship in viewDidLoad of the container controller, all the rotation methods are correctly forwarded to the child.
[self addChildViewController:self.itemsViewController];
But I don't really know if this is the correct way of doing that, since I would like to do all using IB.
Update 2: Thanks to #micantox for his hint to use the "Container View" in the Object Library, I have converted my xib file to a Storyboard and now the child view controller is added to its parent, so I don't have to add it manually from code with addChildViewController and the rotation methods are forwarded as expected.
"Container View" basically implements the embed segue and is supported only from iOS 6.
This is an updated screenshot from my Storyboard:
The right way of creating container views for child view controllers is through the use of the object "Container View" in the Object Library. Dragging one in your View Controller's scene will create a new scene for the child view controller that can be managed separately from the the parent view controller.
Also, if you're trying to create an embed segue to an existing view controller in your storyboard, control-drag from the container view, not the container VC, to the VC you want to embed.
A very simple way to do it is just instantiate the child view controller by referencing its storyboard ID:
UITableViewController *childViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"childViewController"];
[self addChildViewController:childViewController];
[self.view addSubview:childViewController.view];
That way, you can build both view controllers in interface builder. You can set the storyboard ID in interface builder: select the view controller and you'll see a field for it in the identity inspector.

How to navigate between views in storyboard without using Navigationbar or Tab Bar

I have three UIViews in my storyboard, how can I navigate between them with push like animation without using Navigationbar or Tab Bar? I have my custom buttons on views.
Control-click and drag does not work with this error:
Terminating app due to uncaught exception 'NSGenericException', reason: 'Push segues can
only be used when the source controller is managed by an instance of UINavigationController.
You can present/dismiss VCs without using Navigation Controller.
Notice the terminology: push/pop is used for VCs on the Navigation Controller stack, present/dismiss is for VCs on other VCs (not on a Navigation Controller stack).
There are a couple of way to present a VC on top of another VC and it depends on whether that VC exists on your SB as well:
1- If the VC does not exist in your IB and you are just creating and presenting the VC programmatically, you can do:
MyUIViewControllerSubclass *myLittleSubclass=[[MyUIViewControllerSubclass alloc]init];
myLittleSubclass.view.frame=self.view.frame; //this is for exmaple only
[self presentViewController:myLittleSubclass animated:YES completion:nil];
With the above, you obviously would have to add the MyUIViewControllerSubclass Objective C class first to your project (using add files) and import it to whichever class you are putting the above code.
Later to dismiss it, you can use the following code from the MyUIViewControllerSubclass class itself.
[self.parentViewController dismissViewControllerAnimated:YES completion:nil];
2- If you have already added the MyUIViewControllerSubclass Objective C class to your project (using add files) but you intend to use the IB to design it and you have added the VC in the IB and changed its class in the IB to MyUIViewControllerSubclass, you can then use this code:
mySubclass *myLittleSubclass=[self.storyboard instantiateViewControllerWithIdentifier:#"theVC"];
[self presentViewController:myLittleSubclass animated:YES completion:nil];
You can dismiss same as above.
Make sure that you click on the VC in SB and in the identity inspector, put the SB ID as "theVC" and check "Use SB ID".
Hope this helps.
The push animation is only supported when using a UINavigationController inside the parent view. You can embed your view controller in one edit->embed in->navigation controller in IB, and hide the navbar. This may provide the functionality you desire.

UITabbarController dismiss modal UINavigationController

I got a very interesting problem here. My iPhone app has an UITabbarController as rootViewController in the AppDelegate.
If the app is opened the first time, it must be configured basically. For this purpose I create an UINavigationController and tell the tabbarController to present it modally:
firstRun = [[firstRunViewController alloc] init];
navCtrl = [[UINavigationController alloc] initWithRootViewController:firstRun];
[[self tabBarController] presentModalViewController:navCtrl animated:NO];
When the configuration is done, I'd like to get rid of the firstRunViewController. I'm using this technique very often, using -dismissModalViewControllerAnimated:.
But in this constellation this doesn't work. It doesn't matter from what controller I'm calling the dismiss.
I tried it via the tabbarController, the rootViewController, the currently active viewController, of cause self and several other controllers.
EVERY TIME I call -dismissModalViewControllerAnimated: I get this exception:
'UIViewControllerHierarchyInconsistency', reason: 'presentedViewController for controller is itself on dismiss for: <UINavigationController:…
Can anybody help? Thanks in advance, with kind regards, Julian
EDIT
In my AppDelegate I'm using a UITabbarController as rootViewController for the main window:
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
Then I'm creating an UINavigationController and tell the UITabbarController to present the modalViewController:
UINavigationController *navCtrl = [[UINavigationController alloc] initWithRootViewController:firstRun];
[[self tabBarController] presentModalViewController:navCtrl animated:NO];
When I now call -dismissModalViewControllerAnimated: on the firstViewController I'm getting the error from above.
In my opinion you are abusing UITabbarController. This class, even though a subclass of UIViewController, does not really use much of the UIViewController infrastructure.
What you want is a slight extension of what you have now. Create a new UIViewController subclass in your appDelegate, and add it as the single object to an array, and set the tabBar's viewControllers to this array. Set your subclass' hidesBottomBarWhenPushed to YES so it hides the tab bar when it becomes visible.
Now your app will launch and your UIViewController subclass will become the frontmost view. You can make this view the one you wanted to present modally, or you can present that view from your subclass using some kind of animation. Oh, and if you use the launch view as the background image for your subclass, you can really make this a smooth transition - I do this now.
When your modal view is done, then you can instantiate whatever views you want to then display, and set the UITabBarController to use those views with tabBarController.viewControllers (or the animated version). Poof, you UIViewController will get replaces (and under ARC just disappear).
I don't have a chance to test my hypothesis, but I suspect that this issue could depend on the fact that you are presenting the modal view too early, whereby too early means before the main window has had the chance to set up the tab bar controller. So, I would suggest this changes:
create a method to instantiate your navigation controller:
- (void)initializeAndPresentNavigationController {
UINavigationController *navCtrl = [[UINavigationController alloc] initWithRootViewController:firstRun];
[[self tabBarController] presentModalViewController:navCtrl animated:NO];
}
instead of presenting the navigation controller directly from appDidFinishLaunching, call the above method asynchronously:
[self performSelector:#selector(initializeAndPresentNavigationController) withObject:nil afterDelay:0.0];
Here the trick of calling the method as I do in 2 is that the call to initializeAndPresentNavigationController will be simply pushed on the main loop, and executed after your app has had the possibility to build its initial UI.
Hope it works for you.
I finally found the answer myself!
I just couldn't see the wood for the trees! I'm quite happy right now! :)
I did really silly things: In the last viewController of the setup viewControllers I had to change the tabars viewControllers corresponding to whether the user is administrator or not. So I did:
appDelegate.tabBarController.viewControllers = [NSArray arrayWithObjects:appDelegate.readState,
appDelegate.navCtrl,
appDelegate.settings, nil];
You can see that I was adding the AppDelegate's "navCtrl" to the tabbar's viewControllers. So I was trying to dismiss a viewController I just added to the parentViewControllers (UITabbarController) sub-controllers.
Dismissing something I want to present just in the same moment is NOT advisable! :))

Pass information to another viewcontroller without pushing or using segues

I'm trying to "bookmark" (sort of) an object from one UIViewController so that it then shows on a different UIViewController. Currently, the only way I can get this to work is if I either push to the UIViewController that will display the bookmarks or if I perform a segue which is basically the same thing.
Is there a different approach to this?
if you just want to send a variable (without loading the view). This is how I do it.
DetailViewController *detailvc = [[[DetailViewController alloc] init] autorelease];
detailvc.event = [self.fetchedResultsController objectAtIndexPath:indexPath];
And another type of segue I've been doing (without the need of the whole function) i just ask the storyboard to go...
[self.storyboard instantiateViewControllerWithIdentifier:#"detailViewController"];
Just don't forget to name the identifier in the sotyboard, properties, identifier.
Hope it helps...
I've been having some trouble re-learning everything with the storyboard as well.

Tab Based Controller Connection Issues

I have an issue .
I have code that reads in RSS feeds, its navigation based.
RssFunViewController - > thats the view for the table (list of feeds)
NewsDetailViewController - > thats shows more information about the news feed which was selected by user (in a new view).
But when i try to use it in a tab-based navigation project it doesnt work. I just get the table of RSS feeds, When i click an item i dont see the detailed view.
I think my issue is the connection with the tab controller and my classes.
For my 3rd navigation tab I set RssFunViewController as the class.
My question is how do i connect my RSSFunViewController and NewsDetailViewController so when the user clicks the item I see the detailed view.
Heres my current connections in my tab controller:
www.freeimagehosting.net/uploads/535e439c7f.jpg
Thanks everyone.
Maybe I have to disappoint you, but iPhone coding has a very steep learning curve past the drag&drop and connect the dots phase, where you actually have to understand things and make them work using code.
Although the information you give is very limited, here's a brief outline of how the table click action could be handled.
The table should have it's delegate and data source connected to the right class (may be, but does not have to be the same class).
The delegate class should contain a method
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
which will be called when a table entry is tapped. indexPath.row will then give the row number of the tapped entry.
In this method, you could present another view controller showing details, e.g. like:
NewsDetailViewController *ndvc = [[NewsDetailViewController alloc] autorelease];
ndvc.delegate = self;
[ndvc setFeedId:indexPath.row];
[ndvc initWithNibName:#"NewsDetailViewController" bundle:nil];
[self.navigationController pushViewController:ndvc animated:YES];
(assuming the NewsDetailViewController would have a setFeedId method etc.)
or you could have the NewsDetailViewController instantiated in your nib file so you could skip the alloc and initWithNibName steps, and put an "IBOutlet NewsDetailViewController *ndvc;" in the header file so you can connect them.
To remove the highlight from the tapped row, do
[tableView deselectRowAtIndexPath:indexPath animated:YES];
If you're working on a supplied project, you should be able to find lines like these already lying around. Good luck.