为什么顶层布局指南在我的iMessage扩展中移动

我有一个iMessage扩展,我有一些问题,顶部布局指南。 我有一个MSMessagesAppViewController处理演示文稿样式之间的变化。 在我的扩展中,我有一个button。 当它被点击时,我转换到扩展演示文稿样式,然后以模态方式呈现视图控制器。 这是问题:我的第二个VC中的UI隐藏在顶部导航栏的后面。 我认为这很奇怪,因为我把约束条件设置到顶部布局指南。 所以我挖掘了我的代码,并开始debugging顶部布局指南。 我注意到,在我转换到扩展的演示文稿样式之后, topLayoutGuide.length = 86.这就是应该如此。 但是当我以模态方式呈现第二个视图控制器时,顶部布局指南将重置为0.为什么它不是86应该是? 这是我的代码:

在我的主视图控制器:

 @IBAction func addStickerButtonPressed(_ sender: AnyObject) { shouldPerformCreateSegue = true theSender = sender requestPresentationStyle(.expanded) } override func didTransition(to presentationStyle: MSMessagesAppPresentationStyle) { if presentationStyle == .expanded { if shouldPerformCreateSegue == true { shouldPerformCreateSegue = false performSegue(withIdentifier: "CreateStickerSegue", sender: theSender)//here is where I present the new viewController } else { searchBar.becomeFirstResponder() searchBar.placeholder = nil searchBar.showsCancelButton = true searchBar.tintColor = UIColor.white } } else { searchBar.showsCancelButton = false } print(topLayoutGuide.length) //This prints out 86 } 

在另一个模式呈现的视图控制器中:

 override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) self.view.addConstraint(navBar.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor)) print(topLayoutGuide.length) //This prints out 0 } 

作为一种解决方法,我使用UIPresentationController ,它通过topLayoutGuide.length点来移动模态视图控制器:

 class MyViewController: MSMessagesAppViewController { private func presentModalViewController() { let imagePicker = UIImagePickerController() imagePicker.delegate = self imagePicker.sourceType = .savedPhotosAlbum imagePicker.modalPresentationStyle = .custom imagePicker.transitioningDelegate = self present(imagePicker, animated: true, completion: nil) } } // MARK: - UIViewControllerTransitioningDelegate extension MyViewController: UIViewControllerTransitioningDelegate { func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? { let vc = PresentationController(presentedViewController: presented, presenting: presenting) // I really don't want to hardcode the value of topLayoutGuideLength here, but when the extension is in compact mode, topLayoutGuide.length returns 172.0. vc.topLayoutGuideLength = topLayoutGuide.length > 100 ? 86.0 : topLayoutGuide.length return vc } } class PresentationController: UIPresentationController { var topLayoutGuideLength: CGFloat = 0.0 override var frameOfPresentedViewInContainerView: CGRect { guard let containerView = containerView else { return super.frameOfPresentedViewInContainerView } return CGRect(x: 0, y: topLayoutGuideLength, width: containerView.bounds.width, height: containerView.bounds.height - topLayoutGuideLength) } } 

唯一的问题是当你从compact模式调用presentModalViewControllertopLayoutGuide.length172.0 ,原因不明。 所以我必须为这种情况硬编码一个值。

我相信这是在以前的iOS 10testing版已知的错误。 在我将iOS版本升级到最新版本后,我也遇到了同样的问题以及顶部和底部布局指南。

我用了Andrey的一个稍微变化的版本

 class MyViewController: MSMessagesAppViewController { private func presentModalViewController() { let imagePicker = UIImagePickerController() imagePicker.delegate = self imagePicker.sourceType = .savedPhotosAlbum imagePicker.modalPresentationStyle = .custom imagePicker.transitioningDelegate = self present( imagePicker, animated: true, completion: nil ) } } extension MyViewController: UIViewControllerTransitioningDelegate { func presentationController( forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController ) -> UIPresentationController? { let vc = PresentationController( presentedViewController: presented, presenting: presenting ) vc.framePresented = modalBoundaries.frame return vc } } class PresentationController: UIPresentationController { var framePresented = CGRect.zero override var frameOfPresentedViewInContainerView: CGRect { return framePresented } } 

modalBoundaries是一个虚拟UIView约束(通过XIB在我的情况)尊重任何TopLayoutGuide长度。

Interesting Posts