iOS 14中自定义视图控制器转场的Transform处理是否有变更?
Hey there, let's break down what's going on with your UIPresentationController transform issue on iOS 14. First off—yes, Apple did tweak how transforms are handled for presenting view controllers in iOS 14, particularly around animation context timing and coordinate system references, which is likely causing that weird jump you're seeing during dismissal.
What Changed in iOS 14?
iOS 14 introduced adjustments to how the system manages the presenting view controller's layout and animation during modal transitions. Some key shifts include:
- Coordinate system alignment: The system now prioritizes the container view's bounds over screen bounds for layout calculations in UIPresentationController, which can throw off transforms that rely on
UIScreen.main.bounds. - Animation phase timing: During dismissal, the system may reset the presenting view's transform earlier in the animation cycle than in iOS 13, leading to intermediate position jumps before settling on the correct final state.
- Anchor point assumptions: The default anchor point (0.5, 0.5) for the presenting view's layer can cause unexpected shifts when scaling, as iOS 14's layout system handles view positioning relative to the container more strictly.
Fixing Your Transform Code
Let's adjust your transform logic to align with iOS 14's behavior. Here are the key changes to implement:
Use container view bounds instead of screen bounds
Stop relying onUIScreen.main.bounds—your presentation controller's container view is the correct reference frame, as it accounts for safe areas and container layout changes.Adjust the presenting view's anchor point
Set the anchor point to the bottom center of the presenting view to match the system's native modal transition scaling behavior, which eliminates jumpy positioning during animation.Refine the translation calculation
Tweak the translation offset to account for iOS 14's animation context timing.
Here's the updated code:
override func presentationTransitionWillBegin() { super.presentationTransitionWillBegin() // Set anchor point to bottom center for natural scaling guard let presentingView = presentingViewController.view else { return } presentingView.layer.anchorPoint = CGPoint(x: 0.5, y: 1.0) // Update frame to compensate for anchor point change presentingView.frame = presentingView.superview?.bounds ?? presentingView.frame } override func frameOfPresentedViewInContainerView() -> CGRect { guard let containerView = containerView else { return super.frameOfPresentedViewInContainerView() } // Calculate presented view frame based on container bounds let horizontalPadding: CGFloat = 16 let width = containerView.bounds.width - (horizontalPadding * 2) let height = containerView.bounds.height let originY = (containerView.bounds.height - height) / 2 return CGRect(x: horizontalPadding, y: originY, width: width, height: height) } override func transformForPresentedView() -> CGAffineTransform { guard let containerView = containerView else { return .identity } let ratio = (containerView.bounds.width - 32) / containerView.bounds.width let presentingViewHeight = containerView.bounds.height let scaledHeight = presentingViewHeight * ratio // Adjust translation to match iOS 14's animation context let translationY = (presentingViewHeight - scaledHeight) / 2 + 10 return CGAffineTransform(scaleX: ratio, y: ratio) .concatenating(CGAffineTransform(translationX: 0, y: translationY)) }
Additional Checks
- Verify dismiss animation timing: If you're using a custom animator, ensure you're using
UIViewPropertyAnimatorwith the transition context's duration and curve, rather than hardcoding animation parameters. This ensures alignment with iOS 14's system animation timing. - Avoid cached values: Don't cache
frameOfPresentedViewInContainerViewresults—calculate it dynamically each time it's needed, as the container view's bounds can change during rotation or layout updates.
These changes should eliminate the dismissal jump you're seeing, while keeping your transition consistent across iOS 12, 13, and 14.
内容的提问来源于stack exchange,提问作者okoroezenwa

