Hero: modal dismiss animated:NO causes black screen

Created on 6 Jul 2017  路  11Comments  路  Source: HeroTransitions/Hero

when using modal presentation with .overFullScreen (or overCurrentContext)
dismiss(animated: true, completion: nil) works fine
but dismiss(animated: false, completion: nil) causes black screen

hero

here is the test project project.zip

WIP confirmed bug

Most helpful comment

Try with the latest build on master

// instead of 
        dismiss(animated: false, completion: nil)
// use
        dismiss(animated: true, completion: nil)
        Hero.shared.finish(animate: false)

The reason why this is needed it is because Hero stores some state informations on the presentingViewController. If you dismiss without animation, then UIKit will by pass Hero, and Hero is not able to rewind the action.

All 11 comments

Thanks for reporting, will take a look

Try with the latest build on master

// instead of 
        dismiss(animated: false, completion: nil)
// use
        dismiss(animated: true, completion: nil)
        Hero.shared.finish(animate: false)

The reason why this is needed it is because Hero stores some state informations on the presentingViewController. If you dismiss without animation, then UIKit will by pass Hero, and Hero is not able to rewind the action.

Same issue,

Adding Hero.shared.finish(animate: false) make my tabbar disappear...

@Athosone
lkzhao workaround works for me (use branch master)

I don't have the black screen anymore but when my navigationcontroller dismisses,
It hides my tabbar of my tabbarcontroller.

I am on the alpha branch "Installing Hero 1.0.0-alpha.4 (was 1.0.0)"

    meetMeViewController.geolocationRequestData = payload
        meetMeViewController.view.backgroundColor = UIColor.black.withAlphaComponent(0.2)

        let navVC = UINavigationController(rootViewController: meetMeViewController)
        navVC.modalTransitionStyle = .crossDissolve
        navVC.view.backgroundColor = UIColor.clear
        navVC.navigationBar.isHidden = true
        navVC.isHeroEnabled = true

        **navVC.modalPresentationStyle = .overCurrentContext // Is it a problem for Hero?**
        DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
            UIViewController.current()?.present(navVC, animated: true, completion: nil)
        }

In meetme viewcontroller:

.drive(onNext: { [weak self] res in
                if let error = res.1 {
                    print(error)
                    self?.displayAlert(title: NSLocalizedString("alert.error", comment: ""),
                                       message: NSLocalizedString("meetme.response.error", comment: ""),
                                       theme: ERROR, handler: nil)
                    return
                }
                self?.navigationController?.dismiss(animated: true, completion: nil)
                Hero.shared.finish(animate: false)
            }).addDisposableTo(self.disposable)

I'm having the same issue, and the workaround is not working

Same issue here.

When the app is the foreground :

    dismiss(animated: true, completion: nil)
    Hero.shared.finish(animate: false)

works. But when :

  • app is backgrounded while modal is still open
  • tapped on an app notification (which re routes user to some other page after dismissing the modal after app foregrounded) [basically dismissing modal after app is foregrounded from background]
    it does not work :(

Version 1.1.0, IOS 11.2, iPhone6S+

I ran into this issue (inconsistent hierarchy crashes) and found

        dismiss(animated: true, completion: nil)
        Hero.shared.finish(animate: false)

works for me. Will report back if I run in to further difficulties.

Thanks for a great library!!

@Athosone I'm using Rx too. Make sure to wait for the dismiss completion. I use:

public extension Reactive where Base: UIViewController {
    /// Dismiss a view controller and return a Completable
    func dismiss(animated: Bool = true) -> Completable {
        return Completable.create { [weak base = self.base] completable in
            guard let base = base else { return Disposables.create() }
            base.dismiss(animated: animated, completion: {
                completable(.completed)
            })
            return Disposables.create()
        }
    }
}

then instead of drive(onNext:) use a
```
do(onNext: { ... })
.flatMap { _ in
guard let navigator = self?.navigationController else { return .empty() }
navigator.rx.dismiss(animated: true)
}

best of luck!

Hey @k-nar, do you still have this issue?

Was this page helpful?
0 / 5 - 0 ratings