I need to present the classic walkthrough when the Application get launched the first time but, with the implementation that I have in mind, I end up with a structure that keeps the walkthrough as first controller of the hierarchy... and I don't like that. Here is a description of my implementation:
1) In the didFinishLaunchingWithOption I check UsereDefault to catch the first launch
2) If is the first launch I substitute the rootViewController of the window with the walkthrough
3) When the walkthrough is finished I present the first view controller of the App
The problem is with point 3. Presenting the controller from the walkthrough I end up with the whole application presente as modal of the walkthrough... what I want is to completely substitute the walkthrough with the standard first view controller.
Could you suggest a good pattern to show/dismiss a walkthrough?
When you finish Walk-through, replace the rootViewController of your window.
FirstViewController *firstVC = [[FirstViewController alloc] init];
yourAppDelegate.window.rootViewController = firstVC;
Or if you are using storyboard:
FirstViewController *firstVC = (FirstViewController *)[[UIStoryboard storyboardWithName:#"YourStoryboardName" bundle: nil] instantiateViewControllerWithIdentifier:#"YourFirstVCId"];
yourAppDelegate.window.rootViewController = firstVC;
Another option is Show the Walkthrough as modal on top of FirstViewController if it's first time.
Have a look at this library to implement your walkthrough https://github.com/ruipfcosta/SwiftyWalkthrough.
Related
I have the mainstoryboard + viewcontroller
When I press a button on the mainstoryboard it will show another storyboard.
When I press a button in the new storyboard I want to call a function of the mainstoryboard.
How can I make this happen?
You can grab the storyboard and instantiate a viewController from it like this:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"yourStoryboardName" bundle:nil];
YourViewController *viewController = [storyboard instantiateViewControllerWithIdentifier:#"yourViewControllerIdentifier"];
But if you require a function that contains the context of the previous view controller, you should keep a reference to it and just call your methods directly from there. You can also use the presentingViewController property to access the view controller that started the modal presentation. Or if using a navigationController you can use the viewControllers property to access previous viewControllers in the stack.
The comment of Abizem gave me the right tag to search for.
'Protocols'.
I found a very good explanation here on stackoverflow.
Look there:
How to access a previous story board.
Just have a look at the answer of Matt Price. Very nice explanation!
In our storyboard we have multiple UINavigationController stacks. For example, the LoginViewController stack is completely separate from the SWRevealViewController stack.
What's the best practice for switching between them? When I press the logout button (the logout button is on the SWRevealController stack) and then try to present the LoginViewController stack, I get an error like this:
Warning: Attempt to present LoginViewController on SWRevealViewController whose view is not in the window hierarchy!
Even though I'm specifically setting self.window.rootViewController to the Login View Controller's UINavigationController in App Delegate like this:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Spitfire" bundle:nil];
UINavigationController *nav = [storyboard instantiateViewControllerWithIdentifier:#"LoginNavigationController"];
LoginViewController *loginVC = [storyboard instantiateViewControllerWithIdentifier:#"LoginViewController"];
self.window.rootViewController = nav;
[nav presentViewController:loginVC animated:NO completion:nil];
Is there a way I can "dismiss" the current UINavigationController stack and use a new one? Or maybe I shouldn't be calling this code in my app delegate?
I had not played with SWRevealViewController before your question, so my previous response was a little more generic. I've created a sample app here that does its best to throw around as many navigation stacks as possible; I'm sure I've covered your use case.
A few things I'll draw your attention to:
The "main flow" from my previous answer is right smack in the middle of the storyboard; that should help orient you.
SWRevealViewController.m can be used in conjunction with Storyboards and has a very clever hack to do so, but the documentation for it is buried in the implementation. It took me a while to figure out what the hell was happening, but my example app illustrates the usage (two segues, one for "front" and the other for "back", could have a third for "right").
The app's main flow gets completely swapped out for the alternate flow. This is by design of SWRevealViewController. You are essentially switching to an entirely new app.
All sub-flows that are presented modally disrupt the flow.
The author of SWRevealViewController has not provided UIStoryboardSegue subclasses for the replacement of front, rear, and right view controllers. This would be trivial to implement, but I've elected to do the swapping manually in FHKSettingsViewController's implementation.
I repeated code and made dinky classes to make sure what I was doing was obvious.
You should wait to call presentViewController until viewDidAppear on rootViewController.
See here for more discussion: whose view is not in the window hierarchy
Edit:
call presentViewController from your UINavigationcontroller's rootviewController in viewDidAppear: method
-(void)viewDidAppear:(BOOL)animated {
LoginViewController *loginVC = [storyboard instantiateViewControllerWithIdentifier:#"LoginViewController"];
[self presentViewController:loginVC animated:NO completion:nil];
[super viewDidAppear:YES];
}
I'm creating a tour screen where a user would swipe left and right to show some instructional pages.
However I'm having issues in loading pushing the next view. I've created a UINavigationController as below in a handleSwipes method:
TourViewController2 *tourView2 = [[TourViewController2 alloc] initWithNibName:#"TourViewController2" bundle:nil];
UINavigationController* navigationController = [[UINavigationController alloc] init];
[navigationController pushViewController:tourView2 animated:YES];
Any ideas?
Thanks.
As Aniket Kote wrote, you have to not only create UINavigationController, but also make it rootViewController in you application. After done this, UINavigationConroller became a main container and all others vies are placed inside it. For this reason you should not create UINavigationController every time you want to navigate through pages, but only one for all navigation path, eg. when you application in launching.
Next you can use this "global" navigation controller like
[self.navigationController pushViewController:tourView2 animated:YES];
Try this:
TourViewController2 *tourView2 = [[TourViewController2 alloc] initWithNibName:#"TourViewController2" bundle:nil];
UINavigationController* navigationController =[[UINavigationController alloc]initWithRootViewController:tourView2];
self.window.rootViewController=navigationController;
After reading your requirement, i will not go on your approach. I will suggest the use of "Page Control". As defined by Apple below :-
UIPageControl indicates the number of open pages in an application by
displaying a dot for each open page. The dot that corresponds to the
currently viewed page is highlighted. UIPageControl supports
navigation by sending the delegate an event when a user taps to the
right or to the left of the currently highlighted dot.
Hope this helps you !
I'm relatively new to iOS development. I am to move from one viewController to another I use a modal segue transition on button click. This is a game so i want to allow the user to click images to essential move the the app menus.
I have a main page that displays several images, on clicking one i want to be able to move to another view. Currently doing this with a modal segue is causing odd problems with my touchesEnded event where if, for example, i navigate to a page 3 times the touchesEnded event is fired 3 times.
Is there a better way for me to do this or am i just missing thing fundamental?
Thanks
Yes, I think you must make the the navigation controller your root view controller then push views accordingly
UINavigationController * nav = [[UINavigationController alloc] initWithRootViewController:YOUR_BASE_CONTROLLER]
self.rootViewController = nav;
this is in your app delegate.
Then in your action method
[self.navigationController pushViewController:secondViewController animated:YES]
Im assuming you are using the Storyboard to link VCs using segues.
Modal segues are great for simple transitions but really seem to limit what you can accomplish when they are just linked through SB. Ive found that creating an IBAction that includes the following for a VC segue will allow you to not only control your segues more efficiently but also allow you to have a clearer view of what is actually occurring during the transition.
-(IBAction)goToVc:(id)sender{
//Other code to take place during the segue here
//This will identify the Storyboard in use
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
//This will identify the View Controller to switch to
SecondViewController *vc2 = [storyboard instantiateViewControllerWithIdentifier:#"SecondViewControllerID" ];
[self presentViewController:vc2 animated:YES completion:NULL];
}
Every time you perform a modal segue, you lose the UINavigationController that you were previously using. What you need to do is embed a UINavigationController in the view that you are performing a modal segue to.
Check out a question I answered the other day to help you visualize more clearly what I'm talking about.
I am just starting with iPad App development. I want to use splitViewController in my app. I want to use different viewControllers. These will be loaded on rightHandView of an ipad when user selects appropriate on tableviewcontroller present on left hand.
I am using iOS SDK 5.0 without storyboard. I have seen apple's example of multipleDetailView and tried to follow similar procedure but its not working with iOS 5.0 sdk and Xcode4.2, I can not able to access MainWindow.Xib in my project as there is not one when you create project with XCode4.2 and master detail template.
Can anyone tell me how to approach this problem or direct me to appropriate resources ?
Regards,
Sumit
It seems that compared to previous versions, XCode 4.2 generates the relevant code in the "AppDelegate.m" instead of somewhere in the .xib file. I'm not sure about how to work with a MainWindow.xib here, but you could easily push other view controllers in the detail view navigation controller programmatically:
Use the following code for example on a button touch up action:
- (IBAction)buttonClick:(id)sender {
MySecondViewController *vc = [[MySecondViewController alloc] initWithNibName:#"MySecondViewController" bundle:nil];
[self.navigationController pushViewController:vc animated:TRUE];
}
To dismiss the top controller and get back you can use either
[self.navigationController popViewControllerAnimated:TRUE];
in the new top-of-the-stack controller (here MySecondViewController) or just the Back button in the navigation bar.