7

Let's say I have 3 view controller labeled "A","B" and "C". Right now, "A" is the rootViewController of the window and it presents "B" modally when a button is tapped. In "B", when a button is tapped it is supposed to be dismissed by "A" and then "A" will present C modally immediately.How can one do that? Here's my code in hope of achieving this goal but I was unsuccessful in doing so.

At "A" viewController, I declared a property to hold a block at the header file to be called when "B" viewController is dismissed by "A".

@property (nonatomic, copy) void (^presentZapLaunch)(void);

This is "A" viewController present method to present "B"

-(void)presentNextViewCon
{
CYCGestureZapZapViewController *gestureViewCon = [[CYCGestureZapZapViewController alloc]init];

if (!self.presentZapLaunch) {
    __weak CYCZapZapViewController *weakRefCon = self;

    self.presentZapLaunch = ^{
        CYCZapZapViewController *preventWeakRefCon = weakRefCon;

        CYCZapZapLaunchViewController *zapLaunch = [[CYCZapZapLaunchViewController     alloc]init];
        NSLog(@"Called");
        [preventWeakRefCon presentViewController:zapLaunch animated:YES completion:nil];

    };
}


[self presentViewController:gestureViewCon animated:YES completion:nil];

}

This is "B" dismiss method to dismissed by "A" and "A" should present "C" immediately

-(void)presentNextViewCon
{
NSLog(@"Hello");
[self.presentingViewController dismissViewControllerAnimated:self completion:^{[(CYCZapZapViewController *)self.presentingViewController presentZapLaunch];}];

}

*Note that I'm using "A" view controller as the rootViewController of window, and "A" presents "B" view controller modally. All "A","B" and "C" are view controllers.

user3526002
  • 495
  • 2
  • 6
  • 17
  • you can do following : A->B->C and pop the controller B from the stack.So whenever you press back button on controller C, you will be taken to A. – Shubham May 29 '14 at 09:55
  • @Shubham I'm using A as the rootViewController and I'm not using UINavigation Controller for a certain reason. Therefore I presented B view controller modally. Now I want that when B view controller is dismissed by A, A will present C view controller immediately. I don't think presenting modally view controller is using stack. Please tell me if I'm wrong – user3526002 May 29 '14 at 09:58

4 Answers4

9

you can do using protocol let say for example as bellow:-

In to your B viewController setting Protocol :

@class Bviewcontroller;

@protocol BviewControllerDelegate <NSObject>
- (void)BviewcontrollerDidTapButton:
(Bviewcontroller *)controller;

@end

@interface Bviewcontroller : UIViewcontroller

@property (nonatomic, weak) id <BviewControllerDelegate> delegate;
- (IBAction)ButtonTap:(id)sender;

@end

in .m class

- (IBAction)ButtonTap:(id)sender
{
    [self.delegate BviewcontrollerDidTapButton:self];
}

Now in to you A_viewController .h class:

#import "Bviewcontroller.h"

@interface A_viewController : UIViewcontroller<BviewControllerDelegate>

.m class

- (void)BviewcontrollerDidTapButton:
(Bviewcontroller *)controller
{
    [self dismissViewControllerAnimated:YES completion:^{


      // here you can create a code for presetn C viewcontroller 

    }];
}

IMPORTANT when you preseting Bviewcontroller from A_viewController do not set delegate with object like

-(void)presentNextViewCon
{
                bViewcontroller *gestureViewCon = [[bViewcontroller alloc]init];
        gestureViewCon.delegate = self;

[self presentViewController:gestureViewCon animated:YES completion:nil];

}

UPDATE

Here it is i create a demo that working like:

enter image description here

SAMPLE CODE LINK http://speedy.sh/2acSC/modelDemo.zip

Community
  • 1
  • 1
Nitin Gohel
  • 48,603
  • 17
  • 104
  • 138
  • where would you suggest me to set the delegate besides alloc and init another view controller and set it? – user3526002 May 29 '14 at 10:23
  • yes i suggest to use delegate is nice way please check my updated answer i attech sample code link download it and check code as well – Nitin Gohel May 29 '14 at 10:25
  • No, I mean Where would you suggest me to set my delegate to B view controller is not in the presenting method? Are there any other link to the download the code cuz i need to download the downloader to download this code. – user3526002 May 29 '14 at 10:27
  • as you said From A to Present B and from B tap Button that dismiss B and from A after dismiss B then open C. from A so i set Delegate in B that delegate method called in A and dismiss B from A and Open C from A. check Demo you got simply. – Nitin Gohel May 29 '14 at 10:29
  • I know the process but where should i write this code in A controller. Is it in the init method of A controller? Do I have to create Bcontroller in the A's init method and assign it? Bcontroller.delegate = self(Acontroller); – user3526002 May 29 '14 at 10:33
  • did you check sample project and what need of init method? – Nitin Gohel May 29 '14 at 10:34
  • you didn't explain answer for other SO users to understand, and now the sample code has been taken down? – kai Taylor Mar 31 '15 at 16:33
2

You are taking about a Button lets name it controlButton. Pass that button with B and C with custom init method. That means your UIViewController A is having controllButton reference. Using the method

- (void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents 

set the trigger block in A and like this

[_controllButton addTarget:self action:@selector(controllButtonTapped:)....];

- (void)controllButtonTapped:(id)sender {

    [self dismissViewControllerAnimated:YES completion:^{

        // present you c here

        [self presentViewController:c animated:YES completion:NULL];
    }];
}

But the best option is to go with “Mediator Design pattern” where a coordinator is coordinating your present and dismiss actions.

Goppinath
  • 9,729
  • 4
  • 20
  • 41
1

You can not dismiss B and present C simultaneously.

To perform this task you should follow some tasks.

  • On pressing button on 'B' , Dissmiss 'B' without animation and set an global BOOL variable to notify that you want to present 'C'.
  • On -(void)viewDidAppear:(BOOL)animated of 'A'

    if (bool){ [self presentViewController:c animated:YES completion:nil]; }

Sandeep Singh
  • 318
  • 1
  • 8
1

It seems that it is not possible to go from B to C without showing A briefly, which looks unprofessional. However, you can put a black subview over top of A until you've animated to C.

In Swift 3:

class A : UIViewController {
    ...
    func showB() {
        // Adding the black view before dismissing B does not work;
        // the view is not displayed.
        let black = UIView()
        black.backgroundColor = UIColor.black
        black.frame = self.view.bounds // assumes A is not zoomed

        let b = B()
        self.present(b, animated:true, completion: {
            self.view.addSubview(black)
        })

        // Note: self.present() will start the animation,
        // then b.imDone will be set.  It is done here for
        // clarity of what happens next, as if it were all
        // one function.
        b.imDone = {
            b.dismiss(animated:false, completion: {
                self.present(C(), animated:true, completion: {
                    black?.removeFromSuperview()
                })
            })
        }
    }
}

class B : UIViewController {
    var imDone : (() -> Void)?
    ...
    func f()
    {
        imDone?()
    }
    ...
}

class C : UIViewController
{
    ...
}
prewett
  • 1,438
  • 12
  • 18