I want to know if it is possible to have a first view that acts as a menu (that has a couple of buttons for which one is Edit). I want to be able when I click on edit to then show a split view. Now, when I do that, I get the error :
Application tried to present a Split View Controllers modally
My code in the action method of the edit button is :
UIStoryboard *editorStoryboard = [UIStoryboard storyboardWithName:#"EditorStoryboard" bundle:nil];
UIViewController *editorViewController = [editorStoryboard instantiateInitialViewController];
editorViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentViewController:editorViewController animated:YES completion:nil];
So I am assuming, the ViewController that contains the button is the root VC. You should change that with the SplitVC when tapping the button (add a nice animation), because the split should be the root of your app (it should not be presented modally). Hope this helps!
Edit:
It should look something like:
AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
appDelegate.window.rootViewContrller = mySplitViewController;
You can also do this in your custom segue if you have one.
Related
I have been working on this problem for a while and thought I would ask for some help. I have 3 view-controllers: 1 Navigation Controller, 1 Main controller and 1 detail view controller.
Within the main view controller, I have a series of subviews with buttons. Due to the class structure, however, I am unable to directly call self.storyboard to get the current storyboard object.
I have tried 2 different methods, a variety of ways, and am still unsuccessful. I posted my methods below and described what is and what is not happening in each segment. The overall goal is to present a child view controller (the detail view) by tapping a button in a subview, of which does not have access to the parent storyboard directly.
Method 1
//Instantiate the new view controller
ProfileViewViewController *tempViewToShow = [del.window.rootViewController.storyboard instantiateViewControllerWithIdentifier:#"profile"];
// Pass data into the new view controller
tempViewToShow.thisUser = self.postUser;
// Output a simple log to ensure both were created
NSLog(#"Temp User Name: %#, Profile Desc: %#", [tempViewToShow.thisUser getFullName], tempViewToShow.description);
// Using the AppDelegate for the RootViewController, present the detail view
[UIApplication.sharedApplication.delegate.window.rootViewController presentViewController:tempViewToShow animated:YES completion:NULL];
Issues
The issue with this series is that the detail view does not carry the navigation controller (since it is not mentioned), however, this way still shows a full View Controller
Method 2
...
// Use the Delegate and the navigation controller to present the new view controller
[UIApplication.sharedApplication.delegate.window.rootViewController.navigationController presentViewController:tempViewToShow animated:YES completion:NULL];
Issues
Does not display anything
Method 3
// Use the recommended 'pushViewController' for the navigation controller to carry over
[UIApplication.sharedApplication.delegate.window.rootViewController.navigationController pushViewController:tempViewToShow animated:NO];
Issues
Does not display anything
En toto, how would I make this work? What lines would I modify and how? Thanks!
You can solve this issue like this:
ProfileViewViewController *tempViewToShow = [del.window.rootViewController.storyboard instantiateViewControllerWithIdentifier:#"profile"];
UINavigationController *naviController = [[UINavigationController alloc] tempViewToShow];
And then do this :
[UIApplication.sharedApplication.delegate.window.rootViewController presentViewController:naviController animated:YES completion:NULL];
You can create instance of storyboard from storyboard name.once you have correct storyboard instance, get NavigationController from Its identifier, and detailviewController from its identifier. Push detailviewcontroller on Navigationviewcontroller.
get storyboard-- replace name of your storyboard in "MainSToryboard"
UIStoryboard *storyboard =
[UIStoryboard storyboardWithName:#"MainStoryboard"
bundle:[NSBundle mainBundle]];
get instance of Navigationcontroller - replace identifier:
UINavigationController *navController =(UINavigationController *)
[storyboard instantiateViewControllerWithIdentifier:#"navcontroller"];
get detailviewconrtoller :
UIViewController *detailvc=
[storyboard instantiateViewControllerWithIdentifier:#"profile"];
Push detail on current navigationcontroller:
[navController pushViewController:detailvc animated:YES];
I found an alternate solution. The cause was because the incorrect view controller was being called by
UIApplication.sharedApplication.delegate.window.rootViewController.*
The workaround is:
In the primary view controller class, I passed the displayed viewcontroller into the delegate class. Then, from the child class I wanted to call, I referenced that view controller, and navigation controller, and it worked just fine. My final code is below:
// Create the detail View Controller
ProfileViewViewController *tempViewToShow = [del.window.rootViewController.storyboard instantiateViewControllerWithIdentifier:#"profile"];
// Set the user variable in the detail view controller
tempViewToShow.thisUser = self.postUser;
// Push the view controller into the navigation controller
// Note that del.currentNav comes from this code:
/*
* In this class, create the delegate reference
* AppDelegate *del = (AppDelegate *)[[UIApplication sharedApplication] delegate]
*
* In the Delegate class, get the set the current navigation controller {let currentVC : UIViewController = passedInVC}
* self.currentNav = currentVC.navigationController;
*/
[del.currentNav pushViewController:tempViewToShow animated:YES];
I have a main view controller using a navigation controller and i was making my application over that. Now i want to add a welcome view controller for my app and make it show first instead of my main view controller. Is there any way to do it.
What I did was adding a view controller to my storyboard and added two classes of the same name then i made it my root view controller and unchecked the root view controller from the main view but it is not showing on the window. Please help me, that how can i make my welcome view to appear before the main view controller. Thanks
Inside Interface Builder, under the attributes section (looks like a small slider) about a quarter of the way down the list of settings, there is a section labeled "View Controller." The second item in that section is a checkbox "Is Initial View Controller," check that box and you should see the starting arrow of the story board move to the specified view controller and the app should launch to that page.
Hope this Helps.
You could do this programmatically by setting the app window's rootViewController. From the app delegate's application:didFinishLaunchingWithOptions:
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UIScreen *mainScreen = [UIScreen mainScreen];
self.window = [[KTAppWindow alloc] initWithFrame:mainScreen.bounds];
[window makeKeyAndVisible];
window.rootViewController = [[WelcomeViewController alloc] init];
return YES;
}
Then you just need to set up your trigger to switch from the Welcome view to the main view. This could be scheduling an NSTimer, for example. Whatever the trigger is, once it occurs just change the window's rootViewController instance to your MainViewController.
I hope this helps.
It calls "Splash Screen" you just need to add a new ViewController in your Storyboard or if you don't have a Navigation Controller add.
In the Splash class, in the viewDidLoad method you need to put this:
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
HomeViewController *vc = [sb instantiateViewControllerWithIdentifier:#"Home"];
[[[[UIApplication sharedApplication] delegate] window] setRootViewController:vc];
[self performSegueWithIdentifier:#"Home" sender:self];
here you can add conditions if you needed
If I show a viewcontroller in iOS using instantiateViewControllerWithIdentifier, I can not leave the viewcontroller without crashing. The view loads fine and performs its tasks but when i try to leave it by pushing a button the app crashes. Is this because of some state that is wrong or have i made another mistake?
Code:
- (IBAction)push:(id)sender {
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:[[NSBundle mainBundle].infoDictionary objectForKey:#"UIMainStoryboardFile"] bundle:[NSBundle mainBundle]];
NSLog(#"story: %#",mainStoryboard.description);
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
ListViewController *controller = (ListViewController*)[mainStoryboard instantiateViewControllerWithIdentifier: #"ListId"];
appDelegate.window.rootViewController = controller;
}
You're changing the applications root view controller as a result of pressing a button on the previous root view controller. That's not really how navigation in an iOS app should be done. Instead, try embedding your root view controller in a UINavigationController and then push and pop view controllers through it to navigate around your app.
If your interface doesn't fit a navigation paradigm, you could use presentViewController:animated:completion:.
Regardless, you should read the View Controller Programming Guide as it addresses the best practices of displaying views.
I am trying to push a new root controller to a navigation stack, but using a side reveal menu.
My app delegate has the following:
welcomeViewController = [[MyWelcomeViewController alloc] initWithNibName:#"MyWelcomeViewController" bundle:nil];
navController = [[UINavigationController alloc] initWithRootViewController:welcomeViewController];
navController.navigationBarHidden = YES;
// Then we setup the reveal side view controller with the root view controller as the navigation controller
self.revealSideViewController = [[PPRevealSideViewController alloc] initWithRootViewController:navController];
[self.revealSideViewController setDirectionsToShowBounce:PPRevealSideDirectionNone];
[self.revealSideViewController setPanInteractionsWhenClosed:PPRevealSideInteractionContentView | PPRevealSideInteractionNavigationBar];
// Then we make the window root view controller the reveal side view controller
self.window.rootViewController = self.revealSideViewController;
Once the welcome view controller is displayed, the user logs in. Once logged in the following process runs again from the App Delegate.
self.navController.navigationBarHidden = NO;
[self.navController setTitle:#"Home"];
[self.navController pushViewController:homeViewController animated:NO];
I then have a side view controller setup which is a table view with custom cells setup.
When a row is selected I need to push a new root controller onto the navigation controller. I try this by using the following in the table view for the cell selected.
MyAccountViewController *accountViewController = [[MyAccountViewController alloc] init];
[self.navigationController setViewControllers:[NSArray arrayWithObject:accountViewController] animated:NO];
Unfortunately this does not do anything. If I add the code to the App Delegate and then call the method from the table view controller then it works, however not from the .m file for the table view itself. Adding a log I can see the above is run, just does not do anything.
I am unsure if I need to do anything different on the above. For example, completely pop the views currently shown, then create the navigation controller and PPRevealSideViewController all over again. If I am supposed to, I am unsure how to pop all the current views to then push the new to the window, not from the AppDelegate.
The reason I do not want this in the App Delegate is because it is the incorrect way to approach this, and I would then need a separate method for each new root controller I would like to push from the menu, so the App Delegate would become very large.
Check UINavigationController.h:
#interface UIViewController (UINavigationControllerItem)
#property(nonatomic,readonly,retain) UINavigationController *navigationController; // If this view controller has been pushed onto a navigation controller, return it.
It means when you do myViewController.navigationController you will either get nil if myViewController is not pushed to any navController or the navController reference myViewController is pushed into.
As I understand your tableViewController is not pushed into the navController stack, that means you can't get the navController with tableViewController.navigationController. Instead you'll need to use anyViewControllerInTheStack.navigationController or if the navController is the rootViewController of your keyWindow, by
((UINavigationController*)[[UIApplication sharedApplication] keyWindow].rootViewController)
Add something like this to your AppDelegate.h:
#define XAppDelegate ((AppDelegate *)[[UIApplication sharedApplication] delegate])
Now you can access any iVar of AppDelegate from any .m file in your project.
MyAccountViewController *accountViewController = [[MyAccountViewController alloc] init];
[XAppDelegate.navController pushViewController:accountViewController animated:NO];
Make sure you add the correct imports.
One more thing: It's good to pop the login window from your navcontroller once you are done Logging in.
Hope this helps.
My app has a splitview controller, and I when a cell is selected in the detail view, I want to push a view that replaces both the left and right panes.
The code below replaces only the right pane with a custom view.
SecondViewController *secondView = [[SecondViewController alloc]
initWithNibName:NSStringFromClass([SecondViewController class])
bundle:nil];
[[self navigationController] pushViewController:secondView animated:YES];
I would like to load in the left pane another table.
You will want to replace the splitviewcontroller view. What you are doing there is pushing onto whatever navigationcontroller you are on which I assume is your details or your navigation side of the split view controller.
Something like this will brute force it but you'd have to change it for what you need more:
AppDelegate *myDelegate = [[UIApplication sharedApplication] delegate];
[myDelegate.splitViewController.view addSubView secondView.view];
Or maybe try replacing the app delegate rootViewcontroller
myDelegate.window.rootViewController = secondView;
This is all assuming you have the correct properties but you will have to think of a solution that doesn't just push a view controller onto whatever self is in your above code snippet. I hope that helps