iOS 8 - Screen blank after dismissing view controller with custom presentation
This is because you are most likely adding both the presenting
[transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey]
and the presented
[transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]
view controllers to your containerView in the (void)animateTransition:(id )transitionContext method of your animation controller. Since you are using a custom modal presentation, the presenting view controller is still shown beneath the presented view controller. Now since it's still visible you don't need to add it to the container view. Instead only add the presented view controller to the containerView. Should look something like this inside of your animateTransition: method
UIView *containerView = [transitionContext containerView];
UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
// Boolean value to determine presentation or dismissal animation
if (self.presenting){
[transitionContext.containerView addSubview:toViewController.view];
// Your presenting animation code
} else {
// Your dismissal animation code
}
Dismissing modal view controller results in a black screen
I found the solution - this answer really helped. The trick was in dismissing the view controller. It should be done like this:
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
and not like this:
[self dismissViewControllerAnimated:YES completion:nil];
Although the author of the linked answer suggests that a better approach would be to use delegation (presentED VC would define a protocol and presentING VC would subscribe to it and then dismiss the presentED VC once it asks for it), it wasn't feasible in my case.
Black screen when dismissing a UIViewController with custom transition from within a UINavigationController
I figured it out. The problem was when I was adding the view to the transition context container view:
[self.containerView insertSubview:self.fromViewController.view belowSubview:self.toViewController.view];
In stead I needed to add the view from the navigation controller:
[self.containerView insertSubview:navigationController.view belowSubview:self.toViewController.view];
Black screen after presenting modal view controller in current context from UITabBarController
I had the same issue and was able to solve it by setting self.definesPresentationContext = YES;
on the presenting view controller before presenting the modal VC. You can also set this in a storyboard, the checkbox is called "Defines Context" in Interface Builder.
Does a view controller get removed entirely when using a custom transition?
You said:
is my view controller still get removed after the transition finishes or is it still there but off the screen?
There are two completely separate issues here.
First, there is a question of the view controller hierarchy. When you present a new view controller, the old view controller is always kept in the view controller hierarchy so that when you dismiss back to it, it will still be there. However, when you dismiss, the dismissed view controller will be removed from the view controller hierarchy and (unless you do something unusual, like keeping your own strong reference to it somewhere) it will be deallocated.
Second, there is a separate question of the view hierarchy. When presenting, the UIPresentationController
dictates whether the presenting view controller's view remains in the view hierarchy or not. By default, it keeps it in the view hierarchy, but generally if doing a modal, full-screen "present", you'd specify a UIPresentationController
subclass that tells it to remove the presenting view controller's view when the transition is done.
For example, when doing a custom modal "present" transition where the presented view controller's view is opaque and covers the whole screen, then your UIViewControllerTransitioningDelegate
would not only supply the animation controllers, but also specify a presentation controller:
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return YourAnimationController(...)
}
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return YourAnimationController(...)
}
func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
return PresentationController(presentedViewController: presented, presenting: presenting)
}
And that presentation controller might be fairly minimal, only telling it to remove the presenter's view:
class PresentationController: UIPresentationController {
override var shouldRemovePresentersView: Bool { return true }
}
Detecting sheet was dismissed on iOS 13
Is there a way to detect that the presented view controller sheet was dismissed?
Yes.
Some other function I can override in the parent view controller rather than using some sort of delegate?
No. "Some sort of delegate" is how you do it. Make yourself the presentation controller's delegate and override presentationControllerDidDismiss(_:)
.
https://developer.apple.com/documentation/uikit/uiadaptivepresentationcontrollerdelegate/3229889-presentationcontrollerdiddismiss
The lack of a general runtime-generated event informing you that a presented view controller, whether fullscreen or not, has been dismissed, is indeed troublesome; but it's not a new issue, because there have always been non-fullscreen presented view controllers. It's just that now (in iOS 13) there are more of them! I devote a separate question-and-answer to this topic elsewhere: Unified UIViewController "became frontmost" detection?.
Trying to dismiss the presentation controller while transitioning already
My solution:
dismissViewControllerAnimated:completion:If you present several view controllers in succession, thus building a stack of presented view controllers, calling this method on a view controller lower in the stack dismisses its immediate child view controller and all view controllers above that child on the stack. When this happens, only the top-most view is dismissed in an animated fashion; any intermediate view controllers are simply removed from the stack.
For example,I have 4 views:A->B->C->D and when I want to dismiss B, I firstly check if C also want to dismiss by using objc_setAssociatedObject to attach/detach a NSString object, and if C wants to dismiss too,then just cancel C's request.Just call dismiss to B.
Related Topics
No Such File and Directory Found Xcode 7
Swift: Declare an Empty Dictionary
How to Get Distance of Object from iPhone Camera Using Image Exif Meta Data
Change Color of Png in Buttons - iOS
Where Are iOS Simulator Screenshots Stored
Why Tesseract Ocr Library (Ios) Cannot Recognize Text at All
Linker Error in Xcode 5 for Libzbar.A
How to Set the Title of a Navigation Bar Programmatically
Uitableview:Viewforheaderinsection: Not Called During Reloaddata:
Return Lighter Color from Skcolor Using Hsl Lightness Factor
Scrollview and Keyboard in Swift
Launch a Local Notification at a Specific Time in iOS
Xcode 8 Beta - Convert to Current Swift Syntax Failed: Could Not Find Test Host
How to Change the Uisearchbar Search Text Color
iOS App Deployment Without Appstore