Расширение сообщений iOS 10 - неправильный макет при использовании Storyboard Segue
При использовании Segues в приложении расширения сообщений макет портится.
Есть ли способ решить эту проблему, все еще используя storrybord segues?
Скриншоты:
(Примечание: первый и второй View / ViewController идентичны. Тип segue не имеет значения)
Расширенный стиль презентации:
Компактный стиль презентации:
Обновление 1:
Верхний и нижний направляющие макета сбрасываются после перехода
- компактный:
- top: должно быть: 0, но есть: 20
- внизу: должно быть: 44, но есть: 0
- расширен:
- top: должно быть: 86, но есть: 20
- внизу: должно быть: 44, но есть: 0
PS Может кто-нибудь создать новый тег "messages-extension"?
3 ответа
Я надеюсь, что это не всегда будет необходимо, но в итоге я использовал комбинацию выхода ограничения, переменной presentationStyle и viewDidLayoutSubviews() для преодоления этой ошибки / недосмотра.
В моем DetailViewController:
@IBOutlet weak var myViewTopConstraint: NSLayoutConstraint!
var presentationStyle: MSMessagesAppPresentationStyle?
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if presentationStyle == .expanded {
myViewTopConstraint.constant = 86
} else {
myViewTopConstraint.constant = 0
}
}
И в моем MainViewController:
override func willTransition(to presentationStyle: MSMessagesAppPresentationStyle) {
if let detailController = presentedViewController as? DetailViewController {
detailController.presentationStyle = presentationStyle
}
}
И в случае, если это что-то меняет, мой переход представлен модально в виде листа.
В моем приложении viewcontroller в режиме.expand установлен:
view.topAnchor.constraint(equalTo: self.topLayoutGuide.bottomAnchor).isActive = true
в режиме.compact установите значение false
view.topAnchor.constraint(equalTo: self.topLayoutGuide.bottomAnchor).isActive = false
он должен работать.
Одно возможное решение, к которому я пришел с помощью http://sandmoose.com/post/35714028270/storyboards-with-custom-container-view-controllers
В контроллере вида точки входа поместите вид контейнера, который имеет автоматические ограничения макета, выравнивая верх и низ вида контейнера с верхним и нижним направляющими макета.
Затем в само представление контейнера необходимо встроить любой контроллер представления, к которому вы обращаетесь. Таким образом, контроллеры представления назначения всегда будут жить в пределах представления контейнера. Вид контейнера также будет корректно ограничен верхними и нижними направляющими компоновки контроллера начального вида.
Один из способов добиться этого: реализовать протокол, который будет получать уведомления о переходах - что-то вроде:
protocol SegueDelegate {
func willSegue(to: UIViewController)
func didSegue(to: UIViewController)
}
Реализуйте подкласс UIViewController, который имеет ссылку на SegueDelegate, например
class ContainedViewController: UIViewController {
weak var segueDelegate: SegueDelegate?
...
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
segueDelegate?.willSegue(to: segue.destination)
}
}
Пусть ваш начальный контроллер просмотра сообщений реализует протокол.
extension MSMessagesAppViewController: SegueDelegate {
func didSegue(to destination: UIViewController) {
guard let destination = destination as? ContainedViewController else {
return
}
// Reference through IBOutlet or something
containerViewController.embed(destination)
}
}
Контейнер containerViewController должен реализовывать метод встраивания, который заменяет контроллер отображаемого представления на новый, например
class ContainerViewController: UIViewController {
...
func embed(_ viewController: UIViewController) {
let source = childViewControllers.first
if source == viewController {
return
}
source?.willMove(toParentViewController: nil)
addChildViewController(viewController)
if let source = source {
// Do transition here if you want
viewController.view.frame = CGRect(x: 0, y: 0, width: view.frame.size.width, height: view.frame.size.height)
view.addSubview(viewController.view)
viewController.didMove(toParentViewController: self)
source.willMove(toParentViewController: nil)
source.removeFromParentViewController()
} else {
viewController.view.frame = CGRect(x: 0, y: 0, width: view.frame.size.width, height: view.frame.size.height)
view.addSubview(viewController.view)
viewController.didMove(toParentViewController: self)
}
// Assigned in viewDidLoad of MSMessagesAppViewController or similar
segueDelegate?.didSegue(to: viewController)
}
}