AVPlayServiceController在iOS10的弹出窗口中搞乱了底层的模态视图控制器
我有一个应用程序(支持的界面方向-仅纵向),其中包含下一层次的模式显示视图控制器:AVPlayServiceController在iOS10的弹出窗口中搞乱了底层的模态视图控制器,ios,uiviewcontroller,uiinterfaceorientation,avplayerviewcontroller,Ios,Uiviewcontroller,Uiinterfaceorientation,Avplayerviewcontroller,我有一个应用程序(支持的界面方向-仅纵向),其中包含下一层次的模式显示视图控制器: A -> B -> AVP 其中A是位于选项卡栏控制器中的视图控制器,选项卡栏控制器依次是窗口的根 B是一个相当简单的视图控制器,带有按钮、图像和标签,但显示为弹出窗口: // ... presentation method in A let B = // create B B.modalPresentationStyle = .popover B.preferredContentSize = CG
A -> B -> AVP
其中A是位于选项卡栏控制器中的视图控制器,选项卡栏控制器依次是窗口的根
B是一个相当简单的视图控制器,带有按钮、图像和标签,但显示为弹出窗口:
// ... presentation method in A
let B = // create B
B.modalPresentationStyle = .popover
B.preferredContentSize = CGSize(width: 300, height: 400)
B.isModalInPopover = true
if let BPopover = B.popoverPresentationController {
BPopover.delegate = self
BPopover.permittedArrowDirections = []
let window = // grab current window
BPopover.sourceView = window
BPopover.sourceRect = window.bounds
BPopover.passthroughViews = nil
}
self.tabBarController?.present(B, animated: true, completion: nil)
AVP是由B:
// This method is in B.
@IBAction func playVideoButtonPressed(_ sender: Any) {
if let videoURL = self.videoURL {
let videoPlayer = AVPlayer(url: videoURL)
let videoVC = AVPlayerViewController()
videoVC.player = videoPlayer
self.present(videoVC, animated: true, completion: nil)
}
}
在iOS 10.0上,如果执行以下步骤,我会遇到问题:
func popoverPresentationController(_ popoverPresentationController: UIPopoverPresentationController,
willRepositionPopoverTo rect: UnsafeMutablePointer<CGRect>,
in view: AutoreleasingUnsafeMutablePointer<UIView>) {
print("willRepositionPopoverTo")
print(popoverPresentationController)
print(rect.pointee)
print(view.pointee)
}
func-popoverPresentationController(\uPopOverpresentationController:UIPopoverPresentationController,
WillPopOverto-rect:UnsafemeutablePointer,
视图中:AutoreleasingUnsafeMutablePointer){
打印(“Will Popoverto”)
打印(popoverPresentationController)
打印(矩形指针)
打印(view.pointee)
}
它将
视图
大小打印为(w:568;h:320)
,因此,当我旋转AVP控制器时,它似乎会改变我的应用程序的窗口方向,从而调整弹出窗口的大小。虽然它不会尝试重新调整大小:(在我关闭AVP后。根据描述,该应用程序仅设计为纵向模式。在视频模式下旋转设备,会导致您观察到的行为。解决方法是在关闭视频后覆盖方向。尝试添加
let value = UIInterfaceOrientation.portrait.rawValue
UIDevice.current.setValue(value, forKey: "orientation")
查看将出现的功能。这将解决这些随机行为的问题。我已成功复制了您的问题,因此您可以放心,知道这不仅仅是您。我还花了大量时间尝试使用各种“黑客”修复iOS 10行为。我最初没有成功。此外,尽管iOS 11解决了popover的定位问题,但它也引入了标签栏大小(图片)的错误。因此,我的解决方案也需要解决这个问题 : 更新的解决方法 在重新讨论这个问题时,我重新考虑了一个我原先排除的解决方案。结果表明,
avplayervewcontroller
只会影响其父UIWindow
实例的方向。在iOS中使用额外的UIWindow
s并不是一个常用的解决方案,但在这里效果很好
解决方案是使用shimrootViewController
创建一个清晰的UIWindow
,其唯一目的是在它出现的第二次时消除自身动画。此解决方案在iOS 10和iOS 11上同样有效。它不会改变用户体验(除了修复错误)
步骤:
ui窗口
,并使其背景清晰ShimVC
avplayervewcontroller
(这样您就可以获得动画,就像其他方式一样)A->B
然后当用户按下播放器B时,通知A它需要显示AVC。这样你就得到了A->AVC
。当AVC被解除时,我出现了B,所以你回到了A->B
。总体来说,iOS 10或iOS 11上都没有UI问题,但是你的用户将需要等待额外的几分之一秒。如果时间紧迫,您可以禁用(或尝试缩短?)动画,但总体上感觉非常流畅和自然
此外,我建议提交一份关于标签栏大小问题的雷达文件
以下是我的解决方案:
class A: UIViewController, UIViewControllerTransitioningDelegate {
var popover: B?
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if let popover = popover {
if let ppc = popover.popoverPresentationController {
ppc.delegate = self
ppc.permittedArrowDirections = []
let window = view.window!
ppc.sourceView = window
ppc.sourceRect = window.frame
ppc.passthroughViews = nil
}
present(popover, animated: true, completion: nil)
}
}
@IBAction func popover(_ sender: UIButton) {
let b = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "B") as! B
b.modalPresentationStyle = .popover
b.preferredContentSize = CGSize(width: 300, height: 400)
b.isModalInPopover = true
b.delegate = self
if let ppc = b.popoverPresentationController {
ppc.delegate = self
ppc.permittedArrowDirections = []
let window = view.window!
ppc.sourceView = window
ppc.sourceRect = window.frame
ppc.passthroughViews = nil
}
self.popover = b
present(b, animated: true, completion: nil)
}
}
extension A: UIPopoverPresentationControllerDelegate {
func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
return .none
}
}
extension A: BDelegate {
func dismissB() {
popover?.dismiss(animated: true)
popover = nil
}
func showAVPlayerViewController(_ vc: AVPlayerViewController) {
popover?.dismiss(animated: true) {
// Dispatch async allows it to come up in landscape if the phone is already rotated
DispatchQueue.main.async {
self.present(vc, animated: true)
}
}
}
}
protocol BDelegate: class {
func showAVPlayerViewController(_ vc: AVPlayerViewController)
func dismissB()
}
class B: UIViewController {
weak var delegate: BDelegate?
let videoURL: URL? = Bundle.main.url(forResource: "ImAfraidWeNeedToUseMath", withExtension: "m4v")
@IBAction func playVideo(_ sender: UIButton) {
if let videoURL = self.videoURL {
let videoPlayer = AVPlayer(url: videoURL)
let videoVC = AVPlayerViewController()
videoVC.player = videoPlayer
delegate?.showAVPlayerViewController(videoVC)
}
}
@IBAction func done(_ sender: UIButton) {
delegate?.dismissB()
}
}
不幸的是,这并不能解决我的问题。我将它添加到我的弹出式视图控制器
viewwillbeen
方法中。您可以发布一些截图吗?@ArunB在视频播放器前后添加了截图。@iur您正在使用吗?(它应该不在Info.plist中,或者设置为YES。)我最近在使用avplayervewcontroller
时遇到了问题,这是因为它被禁用了。@allenhumpries它不在我的Info.plist中。这不完全是修复方法,但我会接受它作为答案。我最终编写了自己的全屏视频播放器视图控制器,它允许旋转(取决于设备方向,因此即使接口方向仅为纵向也有效)并在iOS10上使用。@iur Th
class A: UIViewController, UIViewControllerTransitioningDelegate {
var popover: B?
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if let popover = popover {
if let ppc = popover.popoverPresentationController {
ppc.delegate = self
ppc.permittedArrowDirections = []
let window = view.window!
ppc.sourceView = window
ppc.sourceRect = window.frame
ppc.passthroughViews = nil
}
present(popover, animated: true, completion: nil)
}
}
@IBAction func popover(_ sender: UIButton) {
let b = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "B") as! B
b.modalPresentationStyle = .popover
b.preferredContentSize = CGSize(width: 300, height: 400)
b.isModalInPopover = true
b.delegate = self
if let ppc = b.popoverPresentationController {
ppc.delegate = self
ppc.permittedArrowDirections = []
let window = view.window!
ppc.sourceView = window
ppc.sourceRect = window.frame
ppc.passthroughViews = nil
}
self.popover = b
present(b, animated: true, completion: nil)
}
}
extension A: UIPopoverPresentationControllerDelegate {
func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
return .none
}
}
extension A: BDelegate {
func dismissB() {
popover?.dismiss(animated: true)
popover = nil
}
func showAVPlayerViewController(_ vc: AVPlayerViewController) {
popover?.dismiss(animated: true) {
// Dispatch async allows it to come up in landscape if the phone is already rotated
DispatchQueue.main.async {
self.present(vc, animated: true)
}
}
}
}
protocol BDelegate: class {
func showAVPlayerViewController(_ vc: AVPlayerViewController)
func dismissB()
}
class B: UIViewController {
weak var delegate: BDelegate?
let videoURL: URL? = Bundle.main.url(forResource: "ImAfraidWeNeedToUseMath", withExtension: "m4v")
@IBAction func playVideo(_ sender: UIButton) {
if let videoURL = self.videoURL {
let videoPlayer = AVPlayer(url: videoURL)
let videoVC = AVPlayerViewController()
videoVC.player = videoPlayer
delegate?.showAVPlayerViewController(videoVC)
}
}
@IBAction func done(_ sender: UIButton) {
delegate?.dismissB()
}
}