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



我有一个iMessage扩展,我有一些问题与顶部布局指南。我有一个MSMessagesAppViewController处理演示样式之间的变化。在我的扩展我有一个按钮。当它被点击时,我转换到扩展的呈现样式,然后模态地呈现一个视图控制器。问题是:我在第二个VC中的UI隐藏在顶部导航栏后面。我认为这很奇怪,因为我设置了顶部布局指南的约束。因此,我仔细研究了我的代码,并开始调试顶层布局指南。我注意到,在我过渡到扩展的表示样式后,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)
    }
}

唯一的问题是当你从紧凑模式调用presentModalViewController时,topLayoutGuide.length172.0,原因不明。所以我必须硬编码一个值

我相信这是之前iOS 10测试版中已知的错误。我也遇到了同样的问题,在我将iOS版本升级到最新版本后,顶部和底部布局指南的效果与我预期的一样。

我使用了一个稍微不同的版本

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长度

最新更新