I have an iMessage extension and I\'m having some issues with the top layout guide. I have an MSMessagesAppViewController
that handles changes between presentation
As a workaround I use UIPresentationController
, which shifts the modal view controller by topLayoutGuide.length
points:
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)
}
}
The only problem is when you're calling presentModalViewController
from compact mode, topLayoutGuide.length
is 172.0
for unknown reason. So I had to hardcode a value for that case.
I believe this was known bug on previous iOS 10 beta. I had same issue and top and bottom layout guide works as I expect after I upgraded iOS version to latest.
I used a slightly varied version of Andrey's
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
being a dummy UIView constrained (via XIB in my case) to respect any TopLayoutGuide length.