Подтвердить что ты не робот

IOS 11 безопасная область

Включает ли руководство по планированию в безопасных зонах, совместимое с iOS ниже 11?

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

4b9b3361

Ответ 1

Мне удалось работать с новыми руководствами по макету Safe Area и поддерживать обратную совместимость с iOS 9 и iOS 10: (EDIT: как указано в комментариях @NickEntin, эта реализация предполагает, что присутствует панель состояния, что не будет истинным в ландшафте iPhone X. В результате на много места на вершину (20 точки), но будет работать отлично.

например. если вы хотите, чтобы представление было на 10 пунктов ниже строки состояния (и на 10 пунктов ниже корпуса датчика на iPhone X):

  • В вашем XIB перейдите к File Inspector и включите сейф, проверив Use Safe Area Layout Guides.
  • Создайте ограничение сверху сверху на верхнюю часть верхнего представления с ограничением >= (больше или равным), константой 30 (30, потому что мы хотим, чтобы 10-точечное расстояние до строки состояния было на 20 пунктов выше) и приоритет High (750).
  • Создайте ограничение сверху сверху на верхнюю часть Safe Area, с = (равным) ограничением, константой 10 и приоритетом Low (250).

То же самое можно сделать для представления внизу (и для ведущего/конечного или левого/правого для безопасной области):

  • В вашем XIB перейдите к File Inspector и включите сейф, проверив Use Safe Area Layout Guides.
  • Создайте ограничение с нижней части представления на нижнюю часть представления, с ограничением >= (больше или равно), константой 10 и приоритетом High (750).
  • Создайте ограничение со дна представления в нижней части Безопасной зоны, с = (равным) ограничением, константой 10 и приоритетом Low (250).

Ответ 2

Обратная совместимость Safe Areas для iOS 9 & iOS 10 работает, только если вы используете раскадровки. Если вы используете xibs, нет руководства по компоновке, к которому можно обратиться. https://forums.developer.apple.com/thread/87329

Обходные пути кажутся либо

(a) перенесите свои xibs в раскадровки или

(б) добавить некоторые дополнительные ограничения программно.

Если (а) на самом деле не вариант, ручной подход будет выглядеть примерно так:

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

  1. Добавьте ограничения в xib между вашим представлением и безопасной областью для iOS 11. Присвойте верхнему ограничению приоритет 750.

    add a top constraint

  2. В вашем контроллере представления добавьте свойство:

    @property (nonatomic, strong) NSLayoutConstraint *topLayoutConstraint;
    

    А затем в viewDidLayoutSubviews:

    - (void)viewDidLayoutSubviews {
        [super viewDidLayoutSubviews];
    
        if (@available(iOS 11, *)) {
            // safe area constraints already set
        }
        else {
            if (!self.topLayoutConstraint) {
                self.topLayoutConstraint = [self.<yourview>.topAnchor constraintEqualToAnchor:self.topLayoutGuide.bottomAnchor];
                [self.topLayoutConstraint setActive:YES];
            }
        }
    }
    

    Новое ограничение будет создано только для iOS 9 & iOS 10 имеет приоритет по умолчанию 1000 и переопределяет приоритет в xib.

  3. Повторите для нижнего ограничения, если вам нужно избежать индикатора дома.

Версия Swift 4:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    if #available(iOS 11, *) {
        // safe area constraints already set
    } else {
        if topLayoutConstraint == nil {
            topLayoutConstraint = <yourview>.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor)
            topLayoutConstraint?.isActive = true
        }
    }
}

Ответ 3

Есть определенно, по крайней мере, одна проблема с обратной совместимостью с ограничениями безопасной зоны iOS 11, которые я наблюдал в контроллерах Xcode 9 GM с токовыми контрольными точками.

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

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

В iOS 11 макет будет правильным в обоих случаях.

Вот простой пример: http://www.filedropper.com/foobar

И вот видео с ним w/nav bar скрыто (iOS 10.3 слева, iOS 11 справа): https://vimeo.com/234174841/1e27a96a87 p >

Здесь версия, в которой отображается панель навигации (включена в бандере): https://vimeo.com/234316256/f022132d57

Я подал это как радар # 34477706.

Благодаря @Sander, чтобы указать видимый случай навигационной панели.

Ответ 4

Да, ваш проект/приложение будет работать в версиях iOS до iOS 11 без каких-либо проблем. В версиях iOS до 11 он заменяет/рассматривает конфигурацию безопасной области в обычном AutoLayout и соответствует правилам руководства по началу и нижней части правил.

Я протестировал свой существующий проект с помощью и без "SafeAreaLayout" на обеих платформах (iOS 11 и обратный iOS 10). Он отлично работает.

Просто убедитесь, что:

  • Если вы разработали свой проект/пользовательский интерфейс в AutoLayout; ограничения вашего UIElement следуют за/сверху и снизу руководство по макету (не для просмотра). Таким образом, одним нажатием кнопки (включить) Опция SafeAreaLayout будет автоматически реализовывать макет SafeArea правильно для всех файлов Interface Builders в вашем раскадровке.

  • Если вы разработали свой проект/пользовательский интерфейс в SafeAreaLayout; то он автоматически будет следовать руководству макета Top и Bottom в назад iOS.

Вот пример моментального снимка с результатом. Включение или отключение макета Safe Area не повлияет на существующий дизайн.

Конфигурация безопасной зоны: введите описание изображения здесь

AutoLayout

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

Короче говоря, ответ на ваш вопрос: "Включение руководств по планированию безопасных областей, совместимых с iOS до 11",

В вашем проекте/приложении вы можете реализовать форму безопасного расположения, и она будет отлично работать с предыдущими версиями iOS преобразование формы безопасной области в верхний и нижний макет.

Ответ 5

Если вы используете xibs без раскадровки, тогда у них нет руководств по расположению на ios 10. Поэтому переместите xib в раскадровку, чтобы иметь обратную совместимость.

Ответ 6

Я использовал это в Objective-C с хорошим результатом для iOS 10. Если вы используете SafeArea в xib, вы можете добавить в viewDidLoad:

if (@available(iOS 11.0, *)) {}
else {
    self.edgesForExtendedLayout = UIRectEdgeNone;
}

Ответ 7

"Руководство по планированию безопасной зоны" совместимо с обратной связью. Ну, если вы не используете его в xib. С раскадрой кажется, что это нормально.

Я решил свою проблему, обратившись к "Верхнему ограничению макета" из первого объекта в верхней части моего представления.

@property (weak, nonatomic) IBOutlet NSLayoutConstraint *topLayoutConstraint;

то я изменил значение Constant на это ограничение и обновил представление. Например, если вы используете навигационную панель (высота 44) плюс строку состояния (высота 20):

if (SYSTEM_VERSION_LESS_THAN(@"11.0")) {
    _topLayoutConstraint.constant = 64;
    [self.view layoutIfNeeded];
}

С SYSTEM_VERSION_LESS_THAN, который определен следующим образом:

#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)

Ответ 8

Я нашел более удобный способ, когда вам нужно всего лишь создать подкласс NSLayoutConstraint, который прикреплен к вашему safeArea.

Это немного странно, поскольку вы должны получить ViewController из UIView, но, на мой взгляд, это простая и хорошая альтернатива, пока Apple окончательно не исправит обратную совместимость для safeArea в Xibs.

Подкласс:

class SafeAreaBackwardsCompatabilityConstraint: NSLayoutConstraint {
private weak var newConstraint: NSLayoutConstraint?

override var secondItem: AnyObject? {
    get {
        if #available(iOS 11.0, *) {}
        else {
            if let vc = (super.secondItem as? UIView)?.parentViewController, newConstraint == nil {
                newConstraint = (self.firstItem as? UIView)?.topAnchor.constraint(equalTo: vc.topLayoutGuide.bottomAnchor)
                newConstraint?.isActive = true
                newConstraint?.constant = self.constant
            }
        }
        return super.secondItem
    }
}

override var priority: UILayoutPriority {
    get {
        if #available(iOS 11.0, *) { return super.priority }
        else { return 750 }
    }
    set { super.priority = newValue }
}
}

private extension UIView {
var parentViewController: UIViewController? {
    var parentResponder: UIResponder? = self
    while parentResponder != nil {
        parentResponder = parentResponder!.next
        if let viewController = parentResponder as? UIViewController {
            return viewController
        }
    }
    return nil
}
}

XIb:

enter image description here

Ответ 9

У меня проблемы с обратной совместимостью с WKWebView и Safe Area на iOS 9. По какой-то причине WKWebView просто игнорирует безопасные настройки макета области.

Ответ 10

В Objective-C для верхнего и нижнего полей, когда на iPhone-X

if (@available(iOS 11, *)) {

    NSLayoutConstraint *bottomConstraint   = [NSLayoutConstraint constraintWithItem:self.childView
                                                                              attribute:NSLayoutAttributeBottom
                                                                              relatedBy:NSLayoutRelationEqual
                                                                                 toItem:self.parentView.safeAreaLayoutGuide
                                                                              attribute:NSLayoutAttributeBottom
                                                                             multiplier:1.0
                                                                               constant:0];


    NSLayoutConstraint *topConstraint   = [NSLayoutConstraint constraintWithItem:self.childView
                                                                       attribute:NSLayoutAttributeTop
                                                                       relatedBy:NSLayoutRelationEqual
                                                                          toItem:self.parentView.safeAreaLayoutGuide
                                                                       attribute:NSLayoutAttributeTop
                                                                      multiplier:1.0
                                                                        constant:0];


} else {

    NSLayoutConstraint *bottomConstraint   = [NSLayoutConstraint constraintWithItem:self.childView
                                                                          attribute:NSLayoutAttributeBottom
                                                                          relatedBy:NSLayoutRelationEqual
                                                                             toItem:self.parentView
                                                                          attribute:NSLayoutAttributeBottom
                                                                         multiplier:1.0
                                                                           constant:0];


    NSLayoutConstraint *topConstraint   = [NSLayoutConstraint constraintWithItem:self.childView
                                                                       attribute:NSLayoutAttributeTop
                                                                       relatedBy:NSLayoutRelationEqual
                                                                          toItem:self.parentView
                                                                       attribute:NSLayoutAttributeTop
                                                                      multiplier:1.0
                                                                        constant:0];

}

Ответ 11

Вот что я сделал с моими проектами

В моем случае оба моих topConstraint и bottomConstraint являются @IBOutlet s. Это также совместимо с iOS 8.

Моя первоначальная конфигурация для верхнего и нижнего ограничений предназначена для обычных iPhone, поэтому я редактирую ограничения только для iPhone X

    // iOS 11 Layout Fix. (For iPhone X)
    if #available(iOS 11, *) {
        self.topConstraint.constant = self.topConstraint.constant + self.view.safeAreaInsets.top

        self.bottomConstraint.constant = self.bottomConstraint.constant + self.view.safeAreaInsets.bottom
    }

.

ПРИМЕЧАНИЕ: self.view - это ваш superView, поэтому я использую его для safeAreaInsets

Ответ 12

Если у вас есть универсальный ViewController, который расширяют все ваши ViewController, другим решением будет поместить элементы, которые должны быть отрегулированы, в IBOutletCollection и программно настроить их в этом GenericViewController. Вот мой код:

@IBOutlet var adjustTopSpaceViews: [UIView]?

override func viewDidLoad() {
    super.viewDidLoad()
    adjustViews()
    ....
}

func adjustViews() {
    guard let views = adjustTopSpaceViews,
        ProcessInfo.processInfo.operatingSystemVersion.majorVersion < 11 else {
            return
    }
    let statusBarHeight = UIApplication.shared.statusBarFrame.height
    for subview in views {
        subview.superview?.constraints.filter({ (constraint) -> Bool in
            return constraint.firstAttribute == .top
                && constraint.secondAttribute == .top
                && (constraint.firstItem as? UIView == subview || constraint.secondItem as? UIView == subview)
        }).forEach({ (constraint) in
            constraint.constant += (constraint.firstItem as? UIView == subview) ? statusBarHeight : -statusBarHeight
        })
    }
}

Ответ 13

Вот моя оболочка решения от iOS 9 до iOS 11+ в быстром 4+

    let safeAreaTopAnchor:NSLayoutYAxisAnchor?
    if #available(iOS 11.0, *) {
        safeAreaTopAnchor = contentView.safeAreaLayoutGuide.topAnchor
    } else {
        // Fallback on earlier versions

        var parentViewController: UIViewController? {
            var parentVCResponder: UIResponder? = self
            while parentVCResponder != nil {
                parentVCResponder = parentVCResponder!.next
                if let viewController = parentVCResponder as? UIViewController {
                    return viewController
                }
            }
            return nil
        }

        safeAreaTopAnchor = parentViewController?.topLayoutGuide.bottomAnchor

    }

Ответ 14

Swift 5

Я просто делаю это. Это просто и очень близко к реальной вещи (только что добавил 'r').

extension UIView {
var saferAreaLayoutGuide: UILayoutGuide {
    get {
        if #available(iOS 11.0, *) {
            return self.safeAreaLayoutGuide
        } else {
            return self.layoutMarginsGuide
        }
    }
}

Используйте вот так:

button.topAnchor.constraint(equalTo: view.saferAreaLayoutGuide.topAnchor, constant: 16)