为什么顶部布局指南在我的 iMessage 扩展中移动
Why is the top layout guide moving in my iMessage extension
我有一个 iMessage 扩展程序,但我在使用顶部布局指南时遇到了一些问题。我有一个 MSMessagesAppViewController
来处理演示文稿样式之间的变化。在我的扩展程序中,我有一个按钮。单击它时,我会转换为扩展的演示样式,然后以模态方式显示视图控制器。问题是:第二个 VC 中的 UI 隐藏在顶部导航栏后面。我认为这很奇怪,因为我将约束设置为顶部布局指南。所以我仔细研究了我的代码并开始调试顶部布局指南。我注意到在我转换到扩展的演示文稿样式后,topLayoutGuide.length
= 86。它应该是这样的。但是当我以模态方式呈现第二个视图控制器时,顶部布局指南重置为 0。为什么它不是 86,因为它应该是?这是我的代码:
在我的主要viewController:
@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
}
我相信这是之前 iOS 10 测试版中的已知错误。在我将 iOS 版本升级到最新版本后,我遇到了同样的问题,顶部和底部布局指南按预期工作。
作为解决方法,我使用 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)
}
}
唯一的问题是当您从紧凑模式调用 presentModalViewController
时,topLayoutGuide.length
是 172.0
,原因不明。所以我不得不为这种情况硬编码一个值。
我使用了 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 长度。
我有一个 iMessage 扩展程序,但我在使用顶部布局指南时遇到了一些问题。我有一个 MSMessagesAppViewController
来处理演示文稿样式之间的变化。在我的扩展程序中,我有一个按钮。单击它时,我会转换为扩展的演示样式,然后以模态方式显示视图控制器。问题是:第二个 VC 中的 UI 隐藏在顶部导航栏后面。我认为这很奇怪,因为我将约束设置为顶部布局指南。所以我仔细研究了我的代码并开始调试顶部布局指南。我注意到在我转换到扩展的演示文稿样式后,topLayoutGuide.length
= 86。它应该是这样的。但是当我以模态方式呈现第二个视图控制器时,顶部布局指南重置为 0。为什么它不是 86,因为它应该是?这是我的代码:
在我的主要viewController:
@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
}
我相信这是之前 iOS 10 测试版中的已知错误。在我将 iOS 版本升级到最新版本后,我遇到了同样的问题,顶部和底部布局指南按预期工作。
作为解决方法,我使用 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)
}
}
唯一的问题是当您从紧凑模式调用 presentModalViewController
时,topLayoutGuide.length
是 172.0
,原因不明。所以我不得不为这种情况硬编码一个值。
我使用了 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 长度。