Включить безопасные области программно

Есть ли способ включить безопасные зоны программно?

Контекст: приложение, над которым я работаю, привязано к iOS 7 в качестве цели, и это, вероятно, не изменится в течение некоторого времени. Xcode не примет включенные безопасные зоны, если я не отключу совместимость с iOS 7 и 8. Большинство просмотров — это XIB. Условно разрешенная безопасная зона была бы идеальной.


person baguIO    schedule 12.12.2017    source источник
comment
Я поместил objective-c в качестве тега для вашего сообщения, потому что предполагаю, что вы не опередили свое время. . Измените, если это необходимо.   -  person LinusGeffarth    schedule 12.12.2017
comment
@LinusGeffarth Swift не работает на iOS 7   -  person baguIO    schedule 12.12.2017
comment
В этом-то и дело ;)   -  person LinusGeffarth    schedule 12.12.2017
comment
@LinusGeffarth Не совсем верно. Swift 2 поддерживает iOS 7.   -  person Tamás Sengel    schedule 12.12.2017
comment
Ребята, я просто сказал, что поставил target-c в качестве тега, потому что я думал, что OP, вероятно, использовал его, и сообщил OP, чтобы они могли изменить его при необходимости.   -  person LinusGeffarth    schedule 12.12.2017


Ответы (1)


Поддержка условных безопасных областей для Xib

Нет, мультиплатформенности Xib не существует. Вы можете попытаться продублировать свои Xib, построить их как Nibs независимо и получить к ним условный доступ во время выполнения в зависимости от версии iOS, но это, безусловно, не рекомендуется делать! У вас будет в два раза больше Xib и сложности для обработки. Гораздо проще поставить ограничения на Superview и изменить их константы из кода в зависимости от safeAreaInsets.

Поддержка Actual Safe Areas для кода

Ситуация аналогична Добавить поддержку макета iPhone X в старый проект Xcode 7/Swift 2:

Единственный способ получить поддержку безопасных областей — это использовать Xcode 9. Поэтому вы должны отказаться от поддержки iOS 7 и Swift 2.

После того, как вы используете Xcode 9, у вас может быть условный код:

Быстрый

extension UIApplication {
    class var safeAreaInsets: UIEdgeInsets {
        if #available(iOS 11.0, tvOS 11.0, *) {
            return UIApplication.shared.delegate?.window??.safeAreaInsets ?? UIEdgeInsets.zero
        }
        return UIEdgeInsets.zero
    }
}

ObjC

@interface UIApplication (extension)
+ (UIEdgeInsets)safeAreaInsets;
@end
@implementation UIApplication (extension)
+ (UIEdgeInsets)safeAreaInsets {
    if (@available(iOS 11.0, tvOS 11.0, *)) {
        UIWindow *window = UIApplication.sharedApplication.delegate.window;
        return window != nil ? window.safeAreaInsets : UIEdgeInsetsZero;
    }
    return UIEdgeInsetsZero;
}
@end

Поддержка смоделированных безопасных зон для кода

Посмотрим правде в глаза, существует не так уж много разных форм устройств для поддержки (всего три случая: портрет с верхним вырезом, альбомный с верхним вырезом, другие). Таким образом, вы можете создать свои собственные значения безопасных областей на основе модели машины, и это может помочь вам со старыми версиями Xcode:

extension UIApplication {
    /// on iPhone X+ portrait: top : 44.0, left : 0.0, bottom : 34.0, right : 0.0
    /// on iPhone X+ landscape: top : 0.0, left : 44.0, bottom : 21.0, right : 44.0
    /// on olders: top : 20.0, left : 0.0, bottom : 0.0, right : 0.0
    class var safeAreaInsetsSimulated: UIEdgeInsets {
        let model: String
        if TARGET_OS_SIMULATOR != 0 {
            model = ProcessInfo.processInfo.environment["SIMULATOR_MODEL_IDENTIFIER"] ?? ""
        } else {
            var size = 0
            sysctlbyname("hw.machine", nil, &size, nil, 0)
            var machine = [CChar](repeating: 0, count: size)
            sysctlbyname("hw.machine", &machine, &size, nil, 0)
            model = String(cString: machine)
        }
        // will need adjustment in 2019
        if model == "iPhone10,3" || model == "iPhone10,6" || model.starts(with: "iPhone11,") {
            switch UIApplication.shared.statusBarOrientation {
            case .landscapeRight, .landscapeLeft:
                return UIEdgeInsets(top: 0, left: 44, bottom: 21, right: 44)
            default:
                return UIEdgeInsets(top: 44, left: 0, bottom: 34, right: 0)
            }
        }
        return UIEdgeInsets(top: 20, left: 0, bottom: 0, right: 0)
    }
}

Обратите внимание, что в первом фрагменте кода я возвращаю UIEdgeInsets.zero по умолчанию, а в последнем фрагменте кода я возвращаю UIEdgeInsets(top: 20, left: 0, bottom: 0, right: 0) по умолчанию: это просто вопрос выбора в зависимости от того, как вы хотите его обрабатывать, потому что Apple сделала выбор переопределить его между iOS 11 и iOS 12, что вызывает много проблем с совместимостью.

person Cœur    schedule 19.09.2018