I have an application with the flow bellow:
Main storyboard: Navigation A -> ViewController A1 (first screen of my app) ... go to some screens and go to other storyboard.
Second storyboard: Navigation B -> ViewController B1 -> ViewController B2 -> ViewController B3.
The normal logic when I'm in B3, tap back button back to B2 and tap back again back to B1 ...
Now I want from B3 go to A1 by click back button. I use this code
UIStoryboard *Main = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *theTabBar = (UIViewController *)[Main instantiateViewControllerWithIdentifier:#"PageController"];
[self.navigationController pushViewController:theTabBar animated:YES];
But it not work as I want (on Main appeared the back button, that was wrong), I changed pushViewController to popViewController but it not work too.
Just right this code on back button of b3:-
[[NSNotificationCenter defaultCenter] postNotificationName:#"takeBack" object:nil];
and write this code on view viewwillappear of A1:-
-(void)viewWillAppear:(BOOL)animated{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(popping) name:#"takeBack" object:nil];
}
-(void)popping{
NSUInteger index=-1;
for (UIViewController *view in [self.navigationController viewControllers]) {
if ([view isKindOfClass:[self class]]) {
index=[[self.navigationController viewControllers] indexOfObject:view];
}
}
[self.navigationController popToViewController:[[self.navigationController viewControllers] objectAtIndex:index] animated:YES];
}
Related
In my app after pressing the login button in my loginViewController, it push to front viewController of my SWRevealViewController. In my RearViewController I have the sign out button. When I press it it should pop to the back viewController again (LoginViewController). But even though I set the button click event like this it doesnt navigate to the loginViewController.
-(void)signOutClick :(id)sender
{
[self performSelectorInBackground:#selector(moveToLoginView) withObject:nil];
}
-(void)moveToLoginView
{
[self.navigationController popToRootViewControllerAnimated:YES];
}
But when I swipe the view it gose to the back view.I want to disable that swipe feature to the back view. And I want to go to the back view when click on the sign out button in my RearViewController. How can I do that? Please help me.
Thanks
I am not sure but instead of using
[self.navigationController popToRootViewControllerAnimated:YES];
try using,
[self.navigationController popViewControllerAnimated:YES];
And to stop swipe gesture you can use code like,
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.revealViewController.panGestureRecognizer.enabled = NO;
}
You need to reset the top view controller if you want to perform these kind of actions off of a click. E.g.
get an instance of the ECSlidingViewController
ECSlidingViewController *slidingController = self.slidingViewController;
get the view controller you wish to be on the top
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *vc = [mainStoryboard instantiateViewControllerWithIdentifier:#"mainViewController"];
UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:vc];
set the topViewController property
slidingController.topViewController = nc;
[slidingController resetTopViewAnimated:NO];
I have this navigation stack
RootVC ---> VC1 --> (presenting)-> ModalVC
and I have VC2 (not in navigation stack).
When presenting ModalVC, I want to click on button in my ModalVC to dismiss ModalVC, then push VC2 into the navigation stack after VC1 at one click. It should look like this:
RootVC ---> VC1 ---> VC2
I tried a lot of methods to make it, but pushing event fire only, when I return to my RootVC.
I tried to make it with delegates:
In ModalVC on click:
[self dismissViewControllerAnimated:YES completion:^{
if ([self.delegate respondsToSelector:#selector(dismissAndPush:)]) {
[self.delegate performSelector:#selector(dismissAndPush:) withObject:VC2];
}
}];
In VC1:
- (void)dismissAndPush:(UIViewController *)vc {
[self.navigationController pushViewController:vc animated:NO];
}
Please help to understand this behavior. Where is my mistake?
From Apple Documentation:
The presenting view controller is responsible for dismissing the view
controller it presented.
So, VC1 should be dismissing the ModalVC, try to do this
ModalVC on click:
if ([self.delegate respondsToSelector:#selector(dismissAndPush:)]) {
[self.delegate performSelector:#selector(dismissAndPush:) withObject:VC2];
}
In VC1:
- (void)dismissAndPush:(UIViewController *)vc {
[self dismissViewControllerAnimated:YES completion:^{
[self.navigationController pushViewController:vc animated:NO];
}];
}
Error has been in other. If Im right understand: some animations before dismissing presented view controller are blocking animations in navigation stack. I solved this problem with 2 ways:
1) deleteting or set right animations before dismissing
2) use setViewControllers in navigation controller (I select it)
- (void)dismissAndPush:(UIViewController *)vc {
[self dismissViewControllerAnimated:NO completion:^{
NSMutableArray *mutableControllers = [NSMutableArray arrayWithArray:self.navigationController.viewControllers];
NSArray *controllers = [mutableControllers arrayByAddingObject:vc];
[self.navigationController setViewControllers:controllers animated:NO];
}];
}
My NSNotification is delayed.
In myVC, I have two buttons, buttonA and buttonB. Each one is linked to their respective pdfs, pdfA and pdfB. There is a button Push, which is pressed after A or B is pressed. Push brings the user to the RVC where there is a UIWebView.
I want it so that by pushing either A or B, the UIWebView will display the respective pdf file. To debug this, I set it so that instead of changing the pdf, it will display text using NSLog. However, it doesn't work until after go back to myVC from the RVC by pressing a different button.
in myVC.m file:
- (IBAction)open_pictures_A:(id)sender
{
//do some button alert popup action/whatever button does
RootViewController *dataObject = [RootViewController new];
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:dataObject
forKey:#"buttonA"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"MyNotification"
object:nil
userInfo:userInfo];
}
And there is one like that for buttonB, but forKey would be "buttonB"
in the viewDidLoad for myVC.m I have
[[NSNotificationCenter defaultCenter] postNotificationName:#"MyNotification"
object:nil];
in my RVC,
RVC.h I have
#property (nonatomic, strong) NSString *property1;
And in the RVC.m I have
- (void)viewDidLoad
{
// other stuff
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(eventListenerDidReceiveNotification:)
name:#"MyNotification"
object:nil];
}
- (void)eventListenerDidReceiveNotification:(NSNotification *)notif
{
if ([[notif name] isEqualToString:#"MyNotification"])
{
NSLog(#"Successfully received the notification from buttonB!");
NSDictionary *userInfo = notif.userInfo;
RootViewController *dataObject = [userInfo objectForKey:#"buttonB"];
// Your response to the notification should be placed here
NSLog(#"dataObject.property1 -> %#", dataObject.property1);
}
}
However, the log entry only shows up when I press a button to exit out of the RVC back to myVC
Here is the code I use to go from mVC to RVC
-(IBAction)goToRVC{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
RootViewController *RVC = [storyboard instantiateViewControllerWithIdentifier:#"Root"];
[UIApplication sharedApplication].delegate.window.RootViewController = RVC;
}
Then from RVC to myVC
-(IBAction)backtomyVC{
[[[UIApplication sharedApplication] delegate] performSelector:#selector(myVC)];
[self disconnect];
}
Why is my notification action being delayed?
It's not because of delay.
When you press your button A or B you create new RVC object and you post the notification however you don't present/push RVC view controller (you just initialise it) so the RVC hasn't fired viewDidLoad method and it hasn't register itself as an observer.
After that you call goToRVC method where you create RVC object and you add it to the view hierarchy so the viewDidLoad method is call and the object register itself as an observer.
When you go back to mVC the RVC is not deallocated yet so it receive the notification and you can see the log.
Hope it's clear.
i am developing a app that has a storyboard with 3 view controllers and app in push notification enabled. and when i receive a push notification and when i tap on notification alert it should open a second view controller from my storyboard let me show my code.
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
[[NSNotificationCenter defaultCenter] postNotificationName:#"pushNotification" object:nil userInfo:userInfo];
}
and then storyboard loads which is actually my first view controller which also have a button in it to second view controller and that is the controller i want to load. and here is the code in my first view controller.
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(pushNotificationReceived) name:#"pushNotification" object:nil];
}
-(void)pushNotificationReceived{
NSString * storyboardName = #"DealerMainStoryboard";
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:storyboardName bundle: nil];
UIViewController * vc = [storyboard instantiateViewControllerWithIdentifier:#"DealerBuyRequests"];
[self presentViewController:vc animated:YES completion:nil];
}
so when i receive notification with this code app crashes when i tap on notification.
You need to get some error log but check this.
UIViewController * vc =
[storyboard instantiateViewControllerWithIdentifier:#"DealerBuyRequests"];
I don't think you want to create a new UIViewController , unless you really named your controller "UIViewController".
So check again the class name of the View you want to present modally
DealerBuyRequestsViewController * vc =
[storyboard instantiateViewControllerWithIdentifier:#"DealerBuyRequests"];
Make sure the StoryBoard Id of this View controller matches DealerBuyRequests or you will get errors.
I have tab bar with navigation controller app using storyboard ,
my purpose is to press a button in tab3 and in the background I want tab1 to "popToRootViewController"
the button in tab3 viewcontroller:
- (IBAction)Action:(id)sender {
vc1 * first = [[vc1 alloc]init];
[first performSelector:#selector(popToRootViewController) withObject:Nil];
}
the code in the tab1 viewcontroller
-(void)popToRootViewController{
[self.navigationController popToRootViewControllerAnimated:NO];
NSLog(#"popToRootViewController");
}
I get the popToRootViewController in logs, but the action didn't perform.
that solve the problem:
- (IBAction)Action:(id)sender {
[[self.tabBarController.viewControllers objectAtIndex:0]popToRootViewControllerAnimated:NO];
}
The way you are doing it:
vc1 * first = [[vc1 alloc]init];
[first performSelector:#selector(popToRootViewController) withObject:Nil];
is not correct. Indeed, you are creating a whole new controller here, completely independent from your existing controllers and not belonging to any navigation controller. For this reason, self.navigationController is nil in popToRootViewController.
You might try doing something like:
//-- this will give you the left-most controller in your tab bar controller
vc1 * first = [self.tabBarController.viewControllers objectAtIndex:0];
[first performSelector:#selector(popToRootViewController) withObject:Nil];
Bind TabBar with tabBarViewController-
In tabBarViewController.m
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
{
NSArray *array = [tabBarController viewControllers];
if([[array objectAtIndex:tabBarController.selectedIndex] isKindOfClass:[UINavigationController class]])
[(UINavigationController *)[array objectAtIndex:tabBarController.selectedIndex] popToRootViewControllerAnimated: NO];
}
It worked perfectly for me.
To press a button in tab3 and in the background I want tab1 to "popToRootViewController"
If you want to perform popToRootViewController in tab1 by pressing button in tab3 then i would like to suggest use NSNotificationCenter. For example follow below code:-
In your firstViewController class add the observer of NSNotification
- (void)viewDidLoad
{
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(yourMethod:)
name:#"popToRootViewControllerNotification" object:nil];
}
-(void)yourMethod:(NSNotification*)not
{
[self.navigationController popToRootViewControllerAnimated:NO];
}
In your ThirdViewController class post the notification in below code:-
- (IBAction)Action:(id)sender {
// vc1 * first = [[vc1 alloc]init];
// [first performSelector:#selector(popToRootViewController) withObject:Nil];
//Post your notification here
[[NSNotificationCenter defaultCenter] postNotificationName:#"popToRootViewControllerNotification" object:nil];
}
If your tab1 and tab2 arein different navigationController, then try this in - (IBAction)action:(id)sender
NSArray *viewControllers = [self.tabbarController viewControllers];
for (UIViewController *viewController in viewControllers) {
if ([viewController isKindOfClass:[vc1 class]]) {
vc1 * first = (vc1 *) viewController;
[first.navigationController popToRootViewControllerAnimated:NO];
}
}