Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to dismiss 2 modal view controllers without weird animation [duplicate]

Tags:

ios

swift

I recreated the question and describe its essence more precisely.

I have two view controllers presented modally on Swift 4, without storyboard (can't use unwind) and without navigation controller

A presents B which presents C.

The reason why we don't use navigation controller, it's because we what simple animation from bottom to top and instead of breaking the standard animation from right to left, we decided to use present.

I would like to dismiss 2 view controllers and go from C to A.

Please, don't mark this question as duplicate before you read my question carefully. I found a tone of similar post, but neither solved my problem. Some of them Objective-C or some of the suggest to use:

self.presentingViewController?.presentingViewController?.dismiss(animated: true, completion: nil)

Or:

self.presentingViewController?.dismiss(animated: false, completion: nil)
self.presentingViewController?.dismiss(animated: true, completion: nil)

It's works, but it create weird animation. It's just delete C and animate dismiss for B:

enter image description here

Expected result:

enter image description here

like image 700
Den Andreychuk Avatar asked Oct 15 '25 18:10

Den Andreychuk


1 Answers

Idea: you need to dismiss third controller with animation and after dismissing you need to dismiss second without animation. While third controller is being dismissed, second shouldn't be visible.


First, set Presentation style of second view controller to Over Current Context when you're presenting it (since we will need to hide its view when we will dismiss third controller)

let vc2 = VC2()
vc2.modalPresentationStyle = .overCurrentContext
present(vc2, animated: true)

continue with creating callbacks properties for willDismiss and didDismiss inside third controller. This callback will be called before and after you dismiss third controller

class VC3: UIViewController {

    var willDismiss: (() -> Void)?
    var didDismiss:  (() -> Void)?

    @IBAction func dismissButtonPressed(_ sender: UIButton) {

        willDismiss?()

        dismiss(animated: true) {
            self.didDismiss?()
        }
    }

}

then in second view controller in the place where you present third view controller, set third controller's callback properties: declare what happens when third controller will dismiss: you need to hide view of second and then after dismissing third you need to dismiss second without animation (view can stay hidden since view controller will be deinitialized)

class VC2: UIViewController {

    @objc func buttonPressed(_ sender: UIButton) {

        var vc3 = VC3()

        vc3.willDismiss = {
            self.view.isHidden = true
        }

        vc3.didDismiss = {
            self.dismiss(animated: false)
        }

        present(vc3, animated: true)
    }

}

enter image description here


Anyway, second option is using UINavigationController and then just call its method popToViewController(_:animated:).

like image 148
Robert Dresler Avatar answered Oct 17 '25 09:10

Robert Dresler