iOS 13 — содержимое исходного кода UIPopoverPresentationController видно на стрелке

Когда я показываю какое-то представление в UIPopoverPresentationController и представляю его как всплывающее окно

popoverCon?.modalPresentationStyle = UIModalPresentationStyle.popover

содержимое переместилось вверх, и некоторая часть отображается стрелкой.

введите описание изображения здесь

Далее у меня была граница вокруг поповера

popoverCon?.view.layer.borderColor = .orange
popoverCon?.view.layer.borderWidth = 1.0;
popoverCon?.view.layer.cornerRadius = 10.0;
popoverCon?.view.layer.masksToBounds = false;

он не показывает часть, где находится стрелка, но отображает небольшую часть линии границы на кончике стрелки.

введите описание изображения здесь

Это работало нормально до iOS 12, но в iOS 13 эта проблема возникает.

Любые предложения о том, как я могу решить эту проблему?


person Hassy    schedule 18.09.2019    source источник


Ответы (9)


Верхняя часть моего содержимого tableView была обрезана стрелкой. Вот как я исправил это в своем случае (код, вставленный в мой файл tableViewController Swift):

override func viewSafeAreaInsetsDidChange() {
    if #available(iOS 11.0, *) {
        super.viewSafeAreaInsetsDidChange()
        self.tableView.contentInset = UIEdgeInsets(top: self.tableView.safeAreaInsets.top, left: 0, bottom: 0, right: 0)
    }
}
person powertoold    schedule 26.09.2019
comment
Установка только верхней вставки не будет работать, вы должны использовать безопасные области. С вашим решением всплывающее окно будет выглядеть странно, если стрелка находится где угодно, кроме верхней. - person SaintMSent; 27.09.2019
comment
С вашим решением всплывающее окно будет выглядеть странно, если стрелка находится где угодно, кроме вершины - в моем случае это не так, но я согласен, что это решение немного взломано - person powertoold; 27.09.2019
comment
@SaintMSent Большое спасибо за этот комментарий. Использование safeAreaLayoutGuides — это правильный путь. - person Warpzit; 28.05.2020

Мое решение в Obj-C, для тех, кому нужно решение obj-c.

Раньше у меня был только popovercontroller, который создавал ошибку, как показано в вопросе. Я переименовал его в childController для ясности и создал содержащий popoverController, чтобы решение, данное @SaintMSent, работало в моей ситуации только с одним исходным представлением. Также использовалось решение https://stackoverflow.com/a/47076040/2148757 и https://useyourloaf.com/blog/self-sizing-child-views/ для соответствующего изменения размера, так как все мои childControllers часто устанавливают предпочтительный размер содержимого.

//Create container popover controller and add child to it
UIViewController* popoverController = [[MyParentPopoverController alloc] init];
[popoverController.view addSubview:childController.view];
[popoverController addChildViewController:childController];
[popoverController setPreferredContentSize:childController.preferredContentSize];
//set popover settings on container
popoverController.modalPresentationStyle = UIModalPresentationPopover;
popoverController.popoverPresentationController.sourceRect = sourceRect;
popoverController.popoverPresentationController.sourceView = buttonView;
popoverController.popoverPresentationController.permittedArrowDirections = direction;
//Fix ios13 'bug' that Apple claims is a feature
UILayoutGuide* guide = popoverController.view.safeAreaLayoutGuide;
childController.view.translatesAutoresizingMaskIntoConstraints = NO;
[childController.view.leadingAnchor constraintEqualToAnchor:guide.leadingAnchor].active = YES;
[childController.view.trailingAnchor constraintEqualToAnchor:guide.trailingAnchor].active = YES;
[childController.view.topAnchor constraintEqualToAnchor:guide.topAnchor].active = YES;
[childController.view.bottomAnchor constraintEqualToAnchor:guide.bottomAnchor].active = YES;
[popoverController.view layoutIfNeeded];
//Show the popover

...

@interface MyParentPopoverController : UIViewController

@end

@implementation MyParentPopoverController

-(void)preferredContentSizeDidChangeForChildContentContainer:(id <UIContentContainer>)container {
    [super preferredContentSizeDidChangeForChildContentContainer:container];
    [self setPreferredContentSize:container.preferredContentSize];
}

@end

Примечание. Я не проверял совместимость с ios11, потому что моя база пользователей не может его использовать.

person Sashah    schedule 24.10.2019
comment
Этот ответ помог мне. Я обернул часть кода ограничения с помощью if (@available(iOS 11, *)), и мне не понадобился подкласс MyParentPopoverController (поскольку в моем приложении размер содержимого не меняется). - person Mark Smith; 31.07.2020

Это определенно функция, они хотят, чтобы вы использовали безопасную зону, начиная с iOS 11, на самом деле, но теперь, похоже, они хотят заставить вас использовать ее.

Была та же проблема, что и у вас, это сработало для меня https://useyourloaf.com/blog/safe-area-layout-guide/

person SaintMSent    schedule 27.09.2019

Определенно ошибка. Когда у вас есть ситуация, когда вы используете UIPopoverArrowDirectionAny, вы увидите, что проблема существует только тогда, когда стрелка находится вверху или слева от всплывающего окна, а не когда стрелка появляется справа или внизу всплывающего окна. Если вы внесете коррективы в свой код для компенсации, он будет работать, если вы используете UIPopoverArrowDirectionUp или UIPopoverArrowDirectionLeft, но не будет правильно отображаться с использованием этой корректировки при использовании UIPopoverArrowDirectionAny, и всплывающее окно появится над или справа от целевого прямоугольника.

person SoftmasterG    schedule 24.09.2019

У меня пока нет «ответа», но я определил, что происходит и почему это так сложно исправить.

ios13 UIPopoverViewController, показывающий UITableViewController - проблемы с безопасной зоной/отсутствующие части таблицы

По сути, любой UITableView с верхними или нижними колонтитулами будет сломан в iOS 13, если только не будет какого-либо способа изменить _UITableViewHeaderFooterViewBackground

Это общеизвестно проблематично и не очень хорошо сочетается с Auto-Layout — об этом известно уже много лет, но Apple никогда не исправляла его и не упрощала работу с ним и не делала его более известным.

https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=video&cd=1&cad=rja&uact=8&ved=0ahUKEwibouuozfvkAhVCXRUIHVGsBegQtwIIKjAA&url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DajsCY8SjJ1Y&usg=AOvVaw3_U_jy9EWH2dJrM8p-XhDQ

https://spin.atomicobject.com/2016/10/12/auto-layout-uitableview/

Я не могу отправить свое приложение в App Store, пока не разберусь с этим. Я надеюсь, что кто-то сможет определить, как манипулировать этим представлением, чтобы оно перестало выталкивать границы таблицы из строя с помощью AutoLayout, что вызывает это вторжение в безопасную область .

person iOSProgrammingIsFun    schedule 01.10.2019

При поиске в Интернете мне помогла следующая ссылка

Твиттер

поэтому мне пришлось добавить безопасную зону и соответствующим образом управлять своими взглядами

CGFloat topPadding = 0.0;
    if (@available(iOS 11.0, *)) {
         topPadding = self.view.safeAreaLayoutGuide.layoutFrame.origin.y;
    }

Быстрый:

var topPadding: CGFloat = 0.0
    if #available(iOS 11.0, *) {
        topPadding = self.view.safeAreaLayoutGuide.layoutFrame.origin.y
    }

но у меня еще нет решения моей пограничной проблемы.

Редактировать: Временно я решил проблему с границей, создав невидимое представление во всплывающем окне и присвоив ему ту же рамку, что и безопасная область, и нарисовав ее границу.

person Hassy    schedule 18.09.2019
comment
Размещено в Apple: 23 сентября 2019 г., 17:43 — FB7316667 - person iOSProgrammingIsFun; 23.09.2019
comment
@iOSProgrammingIsFun это не ошибка, кто-то предоставил ссылку в твиттере, где это указано. Кроме того, если вы используете безопасные зоны, как они хотят, проблема, которую вы описываете, не возникнет (см. мой ответ) - person SaintMSent; 27.09.2019
comment
@iOSProgrammingIsFun это не мой блог. Apple хочет, чтобы вы использовали безопасные зоны для всплывающих окон, начиная с iOS 11, но теперь они заставляют вас это делать. У вас есть представление, принадлежащее контроллеру, который вы представляете во всплывающем окне. Затем у вас есть другое представление, в котором есть ваш контент. А в методе ViewDidLoad вы просто добавляете код, упомянутый в статье, и он создает безопасную зону вокруг вашего контента. Кстати, что касается случая OP, лучшее решение - представить это как модальную страницу, кнопки «Отклонить» и «Готово» вверху лучше подходят для модальных страниц. - person SaintMSent; 28.09.2019
comment
@iOSProgrammingIsFun, если вы используете раскадровку, вы можете применить безопасную зону через построитель интерфейса, как это объясняется в этом блоге. Я сделал это в коде, потому что я не использовал построитель интерфейса для этого контроллера представления. - person SaintMSent; 29.09.2019

Вы должны использовать ограничения. А также обратите внимание на topAnchor. Это должен быть safeAreaLayoutGuide.topAnchor. В моем случае работает корректно. Например:

[NSLayoutConstraint activateConstraints:@[
        [toolbar.leftAnchor constraintEqualToAnchor:self.view.leftAnchor],
        [toolbar.rightAnchor constraintEqualToAnchor:self.view.rightAnchor],
        [toolbar.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor],
        [toolbar.heightAnchor constraintEqualToConstant:50]
    ]];
person Nikita    schedule 25.11.2019

Вставьте содержимое всплывающего окна в другое представление с включенными относительными полями безопасной области. Это должно иметь -21,-21 в качестве источника. Отключите автоматическое изменение размера по вертикали и горизонтали. Кажется, работает, хотя вы теряете автоматическое растяжение.

person Gedalia    schedule 02.08.2021

Настройте содержимое всплывающего окна UIViewController следующим образом:

NSLayoutConstraint.activate([
        myContentView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
        myContentView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
        myContentView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
        myContentView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor)
    ])
person Bryan    schedule 29.09.2020