How to dismiss own view controller and present another view controller in a button tap?
Asked Answered
Z

4

8

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.

Zebulon answered 29/5, 2014 at 9:50 Comment(2)
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.Ability
@Ability 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 wrongZebulon
N
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

Nuncio answered 29/5, 2014 at 10:2 Comment(7)
where would you suggest me to set the delegate besides alloc and init another view controller and set it?Zebulon
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 wellNuncio
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.Zebulon
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.Nuncio
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);Zebulon
did you check sample project and what need of init method?Nuncio
you didn't explain answer for other SO users to understand, and now the sample code has been taken down?Dyeline
H
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.

Horsemanship answered 29/5, 2014 at 10:19 Comment(0)
B
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]; }

Baelbeer answered 29/5, 2014 at 10:41 Comment(0)
F
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
{
    ...
}
Flyblow answered 8/8, 2017 at 23:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.