Question

I'm trying to programmatically change the selected menu item and the displayed topViewController. In other words, I'm trying to do the same one does to change the selected tab in UITabBarController:

[self.tabBarController setSelectedIndex:2];

Therefore, according to another SO question (https://stackoverflow.com/a/20309377/1161723) I'm using this to change the displayed topViewController:

[self.slidingViewController anchorTopViewToRightAnimated:NO];
self.slidingViewController.topViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"MESettingsNavigationController"];
[self.slidingViewController resetTopViewAnimated:NO];

But it doesn't work. Well, the two first lines work correctly, displaying the menu and changing the topViewController, respectively but the last line simply doesn't hide the sidemenu so it stays there until I hide it by gesture or tapping the button. Debugging show that the last self.slidingViewController returns nil instead of instance of ECSlidingViewController. And if I skip the first and the last line, leaving only:

self.slidingViewController.topViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"MESettingsNavigationController"];

it makes the app crash.

Any idea how to change the view properly, with hiding the side menu? I'm using ECSlidingViewController 2.0.1

EDIT: using competition block and/or creating a reference to the sliding view controller doesn't make any difference:

ECSlidingViewController *slidingViewController = self.slidingViewController;
[slidingViewController anchorTopViewToRightAnimated:NO onComplete:^{
    slidingViewController.topViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"MESettingsNavigationController"];
   [slidingViewController resetTopViewAnimated:NO];
}];

UPDATE 14.7.2014:

The sidemenu is not hiding only if custom view controller transitions are used. For instance in TransitionFun example.

The app crashes when leaving only the following in unwind segue handler:

- (IBAction)unwindModalView:(UIStoryboardSegue *)sender
{
    ECSlidingViewController *slidingViewController = [self slidingViewController];
    slidingViewController.topViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"METransitionsNavigationController"];
}

NOTE: If the last view controller (where the unwind segue is called from) is presented by push segue instead of modal segue, the app don't crash.

You can see the hierarchy of the view controllers on the image here

(it's basically the TransitionFun example with one more VC encapsulated in NavigationVC and modally presented by segue from Settings' cell)

Was it helpful?

Solution 2

After some further investigations, I found out that the top view controller's (MyViewController) presentingViewController property returns an instance of ECSlidingViewController instead of MESettingsViewController, even though it was the MESettingsViewController that presented the MyViewController modally.

And because it's ECSlidingViewController that is actually presenting the modal view, the unwind handler wasn't working because it left the modal view on screen.

Solution:

Forget unwind segues, use the following code in the modally presented top view controller (MyViewController) to change the ECSlidingViewController's topViewController property:

- (IBAction)switchToTransitionsScreen:(id)sender
{
    self.slidingViewController.topViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"METransitionsNavigationController"];
    [self.presentingViewController dismissViewControllerAnimated:YES completion:nil];

}

Or use the delegate pattern and put it into MESettingsViewController, for example.

OTHER TIPS

self.slidingViewController is a calculated variable. The calculation is done by navigating the view controller hierarchy. So, if the view controller is removed from the hierarchy as part of your changes then self.slidingViewController will cease to work.

It's also very inefficient to keep calling it. Change to:

ECSlidingViewController *slidingController = self.slidingViewController;

[slidingController anchorTopViewToRightAnimated:NO];
slidingController.topViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"MESettingsNavigationController"];
[slidingController resetTopViewAnimated:NO];

In case someone haven't found answer, I did it in this way.

1- #import "UIViewController+ECSlidingViewController.h" to your menuViewController 2- Set stroboardID of your destinationViewController to "someID" 3- When triggering some action, in backend, use this code:

if(self.slidingViewController.currentTopViewPosition == ECSlidingViewControllerTopViewPositionCentered){
    [self.slidingViewController anchorTopViewToRightAnimated:YES];
}
else{
    self.slidingViewController.topViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"someID"];
    [self.slidingViewController resetTopViewAnimated:YES];
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top