UIViewController 自定义过渡卡在 iOS13
UIViewController custom transition stuck on iOS13
我在我的 iOS 应用程序中实现了两个视图控制器之间的自定义转换,它在 iOS 10、11 和 12 上运行良好。
现在我想使用 Xcode 11 beta 6 和 iOS 13 beta 8 为 iOS 13 做好准备,但过渡停滞了。
自定义转换应该将第一个视图控制器向上移出屏幕,第二个从下向上移动。但现在它回落到 iOS13 默认呈现样式 pageSheet
,只是将第一个视图控制器缩小一点并添加一个暗淡的覆盖层。但是第二个视图没有出现。
我发现在方法 animatePresentation(context: UIViewControllerContextTransitioning)
中 context
没有 return 一个 'from' 视图,所以 context.view(forKey: .from)
returns nil
.
没有 'from' 视图我该怎么办?
FlyUpTransition.swift
class FlyUpTransition: NSObject, UIViewControllerAnimatedTransitioning {
var mode: Mode = .present
enum Mode {
case present
case dismiss
}
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return TimeInterval(0.45)
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
switch mode {
case .present:
animatePresentation(context: transitionContext)
case .dismiss:
animateDismissal(context: transitionContext)
}
}
func animatePresentation(context: UIViewControllerContextTransitioning) {
guard let fromView = context.view(forKey: .from), let toView = context.view(forKey: .to) else { return }
...
}
func animateDismissal(context: UIViewControllerContextTransitioning) {
guard let fromView = context.view(forKey: .from), let toView = context.view(forKey: .to) else { return }
...
}
}
好吧,这很容易,尽管它是 Apple 的一个突破性 API 改变。
viewController.modalPresentationStyle = .fullScreen
现在我必须检查我的整个项目并检查所有模态演示是否仍然符合我的需要。
TL;DR
这是 iOS 中的错误,但您可以使用 context.viewController(forKey:.from).view
作为解决方法。
详细信息
这似乎是 iOS 13.0 中的错误。从 iOS 13.1 beta 3 开始,它仍然存在。 http://www.openradar.me/radar?id=4999313432248320
转换上下文的 view(forKey:)
方法在某些情况下错误地返回 nil。当呈现视图控制器以非模态方式呈现时,view(forKey: .from)
似乎正在发生这种情况。当关闭最初从非模态视图控制器呈现的视图控制器时,view(forKey: .to)
的结果也是 nil。
我不仅在 iPhone 上的新 sheet 样式演示中观察到这一点,而且在 iPad 上以正常形式 sheets 和弹出窗口观察到这一点。
这个问题的另一个表现似乎是 finalFrame(for:)
方法 returns 一个不正确的 CGRect
当被问及这个视图控制器的最终框架应该是什么时。在我的测试中,它返回一个全屏矩形,即使正确的视图更小。
一种解决方法是使用 viewController(forKey:)
方法返回的视图控制器的根视图控制器,尽管 the documentation 明确不鼓励这样做:"The view returned by this method may or may not be the root view of the corresponding view controller."
上面的答案是将 modalPresentationStyle
设置为 .fullScreen
是正确的,但是还值得一提的是,如果您的视图控制器嵌入在 UINavigationController
中,则需要设置它在导航控制器上:
navigationController.modalPresentationStyle = .fullScreen
我通过从集合 VC 拖放到另一个 VC 来在 IB 中设置 segue,后者用于显示详细信息。
我对这个问题有新发现,参考'toView'和'fromView',以下两种方法都有效
间接方式:
transitionContext.viewController(forKey: .to)?.view
transitionContext.viewController(forKey: .from)?.view
直接方式:
transitionContext.view(forKey: .to)
transitionContext.view(forKey: .from)
但是当我将 segue 样式切换为 'Over Full Screen' 时,'toView' 和 'fromView' 的直接方式 return 'nil' 和仅间接方式起作用.
希望这对以后的人有所帮助。
P.S。这是我在 solve another problem 路上的发现,如果您也遇到 'a working animator' 在 iOS 13 及以上
中停止工作的问题,这可能会有所帮助
我在我的 iOS 应用程序中实现了两个视图控制器之间的自定义转换,它在 iOS 10、11 和 12 上运行良好。
现在我想使用 Xcode 11 beta 6 和 iOS 13 beta 8 为 iOS 13 做好准备,但过渡停滞了。
自定义转换应该将第一个视图控制器向上移出屏幕,第二个从下向上移动。但现在它回落到 iOS13 默认呈现样式 pageSheet
,只是将第一个视图控制器缩小一点并添加一个暗淡的覆盖层。但是第二个视图没有出现。
我发现在方法 animatePresentation(context: UIViewControllerContextTransitioning)
中 context
没有 return 一个 'from' 视图,所以 context.view(forKey: .from)
returns nil
.
没有 'from' 视图我该怎么办?
FlyUpTransition.swift
class FlyUpTransition: NSObject, UIViewControllerAnimatedTransitioning {
var mode: Mode = .present
enum Mode {
case present
case dismiss
}
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return TimeInterval(0.45)
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
switch mode {
case .present:
animatePresentation(context: transitionContext)
case .dismiss:
animateDismissal(context: transitionContext)
}
}
func animatePresentation(context: UIViewControllerContextTransitioning) {
guard let fromView = context.view(forKey: .from), let toView = context.view(forKey: .to) else { return }
...
}
func animateDismissal(context: UIViewControllerContextTransitioning) {
guard let fromView = context.view(forKey: .from), let toView = context.view(forKey: .to) else { return }
...
}
}
好吧,这很容易,尽管它是 Apple 的一个突破性 API 改变。
viewController.modalPresentationStyle = .fullScreen
现在我必须检查我的整个项目并检查所有模态演示是否仍然符合我的需要。
TL;DR
这是 iOS 中的错误,但您可以使用 context.viewController(forKey:.from).view
作为解决方法。
详细信息
这似乎是 iOS 13.0 中的错误。从 iOS 13.1 beta 3 开始,它仍然存在。 http://www.openradar.me/radar?id=4999313432248320
转换上下文的 view(forKey:)
方法在某些情况下错误地返回 nil。当呈现视图控制器以非模态方式呈现时,view(forKey: .from)
似乎正在发生这种情况。当关闭最初从非模态视图控制器呈现的视图控制器时,view(forKey: .to)
的结果也是 nil。
我不仅在 iPhone 上的新 sheet 样式演示中观察到这一点,而且在 iPad 上以正常形式 sheets 和弹出窗口观察到这一点。
这个问题的另一个表现似乎是 finalFrame(for:)
方法 returns 一个不正确的 CGRect
当被问及这个视图控制器的最终框架应该是什么时。在我的测试中,它返回一个全屏矩形,即使正确的视图更小。
一种解决方法是使用 viewController(forKey:)
方法返回的视图控制器的根视图控制器,尽管 the documentation 明确不鼓励这样做:"The view returned by this method may or may not be the root view of the corresponding view controller."
上面的答案是将 modalPresentationStyle
设置为 .fullScreen
是正确的,但是还值得一提的是,如果您的视图控制器嵌入在 UINavigationController
中,则需要设置它在导航控制器上:
navigationController.modalPresentationStyle = .fullScreen
我通过从集合 VC 拖放到另一个 VC 来在 IB 中设置 segue,后者用于显示详细信息。
我对这个问题有新发现,参考'toView'和'fromView',以下两种方法都有效
间接方式:
transitionContext.viewController(forKey: .to)?.view
transitionContext.viewController(forKey: .from)?.view
直接方式:
transitionContext.view(forKey: .to)
transitionContext.view(forKey: .from)
但是当我将 segue 样式切换为 'Over Full Screen' 时,'toView' 和 'fromView' 的直接方式 return 'nil' 和仅间接方式起作用.
希望这对以后的人有所帮助。
P.S。这是我在 solve another problem 路上的发现,如果您也遇到 'a working animator' 在 iOS 13 及以上
中停止工作的问题,这可能会有所帮助