My app is a 5 tabviewcontroller app.
I want to build a first run set up routine that will collect info from the user in five steps (5 UIViews).
This GUI should hide my entire application GUI during the set up, in a similar way that happens when you restore an iPhone and have it set up for wi-fi, iCloud, etc...
I am trying
[self presentViewController:firstRunSetUp_1_ViewController animated:YES completion:NULL]
But this does not allow me to push the following view controllers.
UPDATE:
This is my code in appDidFinishLauching in appDelegate:
BHfirstRunSetUp_1_ViewController *f = [[BHfirstRunSetUp_1_ViewController alloc]init];
[self.myTabBarController.selectedViewController presentViewController:f animated:NO completion:NULL];
This is code inside "nextButtonClicked" IBAction, inside the BHfirstRunSetUp_1:
-(IBAction)nextButtonClicked:(id)sender
{
NSLog(#"inside nextButton clicked...");
// initialize second view controller:
if (firstRunSetUp_2_ViewController == nil) {
firstRunSetUp_2_ViewController = [[BHfirstRunSepUp_2_ViewController alloc]init];
}
[self.navigationController pushViewController:firstRunSetUp_2_ViewController animated:YES];
}
I have these lines in console:
2013-08-01 20:20:33.106 iNota[3245:907] inside nextButton clicked...
But the view isn't pushed!
Here is a screen shot:
http://www.idanfe.com/images/1.png "screenshot"
+++ UPDATE 2 ++++
I have taken Apple's Tabster example and changed it, adding my lines. You find a copy here:
http://www.idanfe.com/sample/Tabster.zip "Tabster"
Push a UINavigationController. eg:
UINavigationController * navigationController = [[UINavigationController alloc] initWithRootViewController:firstRunSetUp_1_ViewController];
[self presentViewController:navigationController animated:YES completion:NULL];
You can push them into section using as a modal view, but suggestion is to use uinavigationviewcontroller which is a rootviewcontroller in window ( in app delegate ).
If I understand what you're asking for, just present a navigation controller in the first step, which will show the root view controller of that navigate controller. Then push to your other 4 setup controllers. When you're done, dismiss the navigation controller.
Related
Ok, I'm still pretty new; so, please bear with me.
I'm creating a custom app for a friend that displays a list of work orders in a table view. Clicking on a work order brings them to a detail view. In the detail view, there is a button that uses a push to present another screen called completion view. From the completion view, they click a button that uses the following code to present a nib for signature capture.
SigScreenViewController *sigScreenViewController=[[SigScreenViewController alloc] initWithNibName:#"ViewController_iPhone" bundle:nil];
[self presentViewController:sigScreenViewController animated:YES completion:nil];
The signature screen uses: https://github.com/jcmontiel/SignatureViewExample for capturing the signature and does it well. I have a button that completes the transaction and sends it back to the table view list.
My problem is that I cannot create a button that will return me to the completion view in the storyboard.
I've tried the following in a button:
[self dismissViewControllerAnimated:YES completion:nil];
or
[self.navigationController popViewControllerAnimated:YES];
I'm open for any suggestions on how I can do it.
Thanks in advance!
Have you tried having the UIViewControllers embedded in a navigation controller ?
Are you pushing from a UIViewController in UIStoryboard to a NIB file?
If so check out this sample project that pushes from storyboard to a NIB:
// in a navigation controller
// to load/push to new controller use this code
// this will be next screen
DetailsViewController *detailsViewController = [[DetailsViewController alloc ]init];
[self.navigationController pushViewController:detailsViewController animated:YES];
// to go back or pop controller use this
// now it will send back to parent screen
[self.navigationController popViewControllerAnimated:YES];
How can to go back to previous view programmatically without UINavigationController, because all examples that I have found use UINavigationController ?
I am making view for sending feedback and I would like to use this view in many more apps.
If I use UINavigationController than app need to have UINavigationController to use my view for sending feedback.
Is this possible to do and how ?
This is code how I show my view for sending feedback:
- (IBAction)showFeedbackView:(id)sender {
WOC_FeedbackViewController *feedbackView = [[WOC_FeedbackViewController alloc] init];
[self presentViewController:feedbackView animated:YES completion:nil];
}
Use this to go back
[self dismissViewControllerAnimated:YES completion:nil];
Depending on what your project works (Storyboards or XIB) you can use presentViewController. But thats when you keep a reference on your last viewController's identifier.
If you know the ID of your viewController NSString *yourID;
1) Init your viewController
For storyboard
UIViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:yourID];
For XIB
UIViewController *vc = [UIViewController alloc]initWithNibName:yourID bundle:nil];
2) Presenting your ViewController
[self presentViewController:vc animated:YES completion:nil];
P.S This is a way to do this, but you should use navigationController because you can keep memory of a viewController on stack so when you need to access it again, you can access it faster. In other words, UINavigationController is applied in every iOS Application you see on App Store.
In Swift, you can use following line of code to go back to previous view controller without navigation controller:
self.dismissViewControllerAnimated(true, completion: nil)
In android, switching between activities, is fairly straightforward
you call
Intent intent = new Intent(this,NextActivity.class); <- define the next activity
startActivity(intent); <- start the next activity
finish(); < -get rid of the current activity
now in iOS i know how to do this:
UIViewController *nextviewcontroller = [[UIViewController alloc]initWithNibName:#"nextvc" bundle:nil];
[self presentViewcontroller:nextviewcontroller animated:YES completion:nil];
How do I get rid of the current view controller? so that currentviewcontroller dies after presenting nextviewcontroller ?
[self dismissViewController:YES]; doesnt seem to do the trick
the lifecycle methods viewWillDisappear and viewDidDisappear are called even if I don't call [self dismissViewController:YES];
i want "currentviewcontroller" to be removed from the memory, and from the viewcontroller stack, so that clicking "back" in "nextviewcontroller" will go to some thirdviewcontroller that was before currentviewcontroller
In iOS is different, since there's no concept of Activity and everything is more focused on the app itself (in Android you can mix activities from different apps). Therefore, there's no concept of "view controller stack".
The most similar concept is the "navigation stack" of navigation controllers, where you actually push and pop new view controller into some kind of linear navigation. A navigation bar is automatically created and populated with back buttons.
presentViewController will show your view controller modally upon the current one, but you can't thrash the presenting one since it's holding and containing ("defining context") the new one.
If you use a navigation controller for your navigation hierarchy (I don't know if you can), you can override the back button and use something like
UIViewController * prev = self.navigationController.viewControllers[self.navigationController.viewControllers.count -2 ]
[self.navigationController popToViewController:prev animated:YES]
With a modal view controller, you may try something like (I haven't tried but it may work)
[self.presentingViewController.navigationController popViewControllerAnimated:YES]
You should write one of these code into the target action of your close button.
iOS doesn't maintain a global stack of controllers in the way that Android does. Each app shows a controller at its root, and that one is responsible for showing the other controllers in the app. Controllers can display other controllers modally using presentViewcontroller:animated:completion: but the presenting controller remains underneath the presented one.
If your current controller is the root controller, then instead of using presentViewcontroller:animated:completion: you'd just do this:
self.view.window.rootViewController = nextViewController;
It's very common for the root controller to be a UINavigationController, which does manage a stack of controllers. If that is the case, and if your current controller is at the top of the stack, you'd do this:
[self.navigationController popViewControllerAnimated:NO];
[self.navigationController pushViewController:nextViewController animated:YES];
If your setup is different, you'd do something different; it's hard to say what without knowing more. But it's most likely that you'd be in the UINavigationController case.
In the viewDidAppear of your nextviewcontroller you could add :
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
NSArray *controllers = self.navigationController.viewControllers;
NSMutableArray *newViewControllers = [NSMutableArray arrayWithArray:controllers];
[newViewControllers removeObjectAtIndex:[controllers count]-2];
self.navigationController.viewControllers = newViewControllers;
}
There is nothing available like this in iOS but you can achieve it doing something like below
NSArray *viewControllers=[self.navigationController viewControllers];
NSMutableArray *newControllers=[[NSMutableArray alloc] init];
for(int i=[viewControllers indexOfObject:self];i<viewControllers.count;i++){
[newControllers addObject:[viewControllers objectAtIndex:i]];
}
[self.navigationController setViewControllers:[[NSArray alloc] initWithArray:newControllers]];
I have tried the method of storing all the view controllers in an array but it didn't work for me . When you try popViewController it will move to the View Controller which is last in the stack.
You can make 2 navigation controllers and switch between them and also switch between the view controllers of a particular Navigation Controller.
For eg.
You can switch between 2 Navigation Controller using the following code:
FirstNavController *fisrtView=[storyboard instantiateViewControllerWithIdentifier:#"firstnavcontroller"];
self.window.rootViewController = firstView;
}else{
SecondNavController *secondView=[storyboard instantiateViewControllerWithIdentifier:#"loginnavcontroller"];
self.window.rootViewController = secondView;
}
If your FirstNavController has 2 ViewControllers then you can switch between them using pushViewController
SecondViewController *sc = [self.storyboard instantiateViewControllerWithIdentifier:#"secondviewcontroller"];
[[self navigationController] pushViewController:sc animated:YES];
and popViewController
[self.navigationController popViewControllerAnimated:YES];
The basic design of app storyboard goes like this:
Top Level#1
Navigation Controller --> View Controller (Front) contains button "Show Master"
Next Level#2
Navigation Controller --> View Controller (Master) --> push --> View Controller (Detail)
When I run the app in simulator, Front View Controller page appears.
Requirement: On "Show Master" button click, I wanted the control focused to Master. When something done here, either show Detail view Controller or swing back to Front view Controller. How to code this from Front.M and Master.M.
Setup: iOS 6.x, XCode 5.x
Note: Below code exists in Front.M but it does not work, brings up Master page in black
vwMaster *vc = [[vwMaster alloc] init];
vc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:vc animated:YES completion:NULL];
Any thought?
It looks like you're most of the way there, but that vwMaster has no layout information associated with it. One way to provide this would be to create a .xib file with the same name as your view controller class (i.e. vwMaster.xib) and set the xib file's owner to vwMaster. Your existing code should then work.
It seems like you're using Storyboard, however, in which case you have several options:
The easiest option. In Storyboard, ctrl-drag from the button in the Front view controller to the Master view controller. select a modal segue type.
Create a modal segue between the Front and Master view controllers in Storyboard by ctrl-dragging between them, give the segue an identifier (e.g. "vwMaster") in the attributes inspector and trigger the segue in code:
[self performSegueWithIdentifier:#"vwMaster" sender:self];
Give the vwMaster view controller itself an identifier in the identity inspector in storyboard and present that as you were before:
vwMaster *vc = (vwMaster *)[self.storyboard instantiateViewControllerWithIdentifier:#"vwMaster"];
vc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:vc animated:YES completion:NULL];
Regardless of the route you choose, you're likely to want use the delegate pattern to dismiss your view controller. For this and more, I suggest you read the relevant apple Docs:
https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/ModalViewControllers/ModalViewControllers.html
if you use navigationcontroller y u no use push and pop instead presenting viewController?
Thanks knellr.
I have been playing with different flows. I am able to goto view by calling
[self performSegueWithIdentifier:#"name" sender:self] - provided name'm.
Also have strong code handling - in cases where data to be passed out
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
//NSLog(#"prepareForSegue: %#", segue.identifier);
if ([[segue identifier] isEqualToString:#"name"])
{
}
}
I have a view that requires user to be logged in. When the user attempts to open that view an he is not logged in I will call the login view for him to login and after he is done I will call the original view that he intended to see.
On iPhone this works fine as I push view controllers there.
But on iPad where I present view controller this does not work. It says that dismissal in progress, can't show new controller. Here is the code:
- (void) buttonPressed
{
if (!userLoggedIn) { // userLoggedIn getter calls new screens of login if needed
return; // this is executed if user declined to login
}
MyViewController *temp = [[MyViewController alloc] init];
[self.navigationController presentViewController:temp animated:YES]; // this returns warning that dismissal in progress and does not work
}
What can I do about that? On iPhone all of my logic works fine, but on iPad it fails. I use it in many places and completely rewriting code is not good.
EDIT: more code:
- (BOOL) userLoggedIn {
// code omitted
[centerController presentViewController:navController animated:YES completion:nil];
// code omitted
[centerController dismissViewController:navController animated:YES]; // setting to NO does not fix my problem
return YES;
}
EDIT2:
This is the code for iPad. I have removed iPhone-related code. What it does on iPhone - instead of presenting controller it uses pushing, and in that situation everything works fine.
You cannot present another view as long as the dismissing of your 1st view is not complete. The animation of dismissing view should be completed before presenting new view. So, either you can set its animation to NO while dismissing, or use
performSelector:withObject:afterDelay:
and present the next view after 2-3 seconds.
Hope this helps.
You've not posted enough code to really see what you're doing, but one approach to the problem of dismissing and pushing view controllers clashing in this way is to make a the pop+posh into a single atomic operation operation, rather then seqential operations.
You can do this by using the setViewControllers:animated: method on UINavigationController. This allows you to effectively remove one or more view controllers, and add one or more view controllers, all as one cohesive operation, with one seamless animation.
Here's a simple example:
[self.navigationController pushViewController:loginController];
// ... later on, when user login is validated:
NSMutableArray *viewControllers =
[self.navigationController.viewControllers copy];
[viewControllers removeLastObject];
[viewControllers addObject:[[MyNewViewController alloc] init]];
[self.navigationController setViewControllers:viewControllers animated:YES];
If you do things this way, your code will be more predictable, and will work across iPhone and iPad.
For more info, see the API docs.
Update
Since your problem involves a modal dialog on top, try using setViewControllers:animated:NO to change the nav controller stack underneath the modal login dialog before you dismiss the modal.