xcode - iOS 11 تخطيط منطقة آمنة للتوافق مع الوراء




compatibility iphone-x safearealayoutguide (12)

إن التوافق مع الإصدارات السابقة من المناطق الآمنة لنظامي التشغيل iOS 9 و iOS 10 يعمل فقط إذا كنت تستخدم القصص المصورة. إذا كنت تستخدم xibs ، فلا يوجد دليل تخطيط للتراجع. https://forums.developer.apple.com/thread/87329

تبدو الحلول إما

(أ) ترحيل xibs الخاص بك إلى القصص المصورة ، أو

(ب) إضافة بعض القيود الإضافية برمجيًا.

إذا لم يكن (a) خيارًا في الحقيقة ، سيكون المنهج اليدوي شيئًا كالتالي:

بافتراض أن لديك عرض في xib الذي تريد الاحتفاظ به داخل المنطقة الآمنة (أي تحت أي شريط حالة أو شريط تنقل).

  1. أضف قيودًا في xib بين العرض والمنطقة الآمنة لنظام التشغيل iOS 11. قم بتعيين القيد العلوي على أولوية 750.

  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. كرر لقيد القاع إذا كنت بحاجة إلى تجنب مؤشر المنزل.

سويفت 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
        }
    }
}

هل يمكّن دليل تخطيط المناطق الآمنة متوافقًا مع نظام التشغيل iOS دون 11؟


في 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];

}

"دليل تخطيط المناطق الآمنة" متوافق مع الإصدارات السابقة. حسنا ، إلا إذا كنت تستخدم في xib. مع القصة المصورة يبدو موافق.

لقد حلت مشكلتي عن طريق الوصول إلى "القيد التخطيطي العلوي" من الكائن الأول في أعلى وجهة نظري.

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

ثم قمت بتغيير القيمة الثابتة إلى هذا القيد وتحديث العرض. على سبيل المثال ، إذا كنت تستخدم شريطًا للتنقل (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)

لدي مشكلات في التوافق مع WKWebView & Safe Area على iOS 9. لسبب ما ، يتجاهل WKWebView ببساطة إعدادات تخطيط المناطق الآمنة.


كنت أستخدم هذا في Objective-C مع نتيجة جيدة لنظام التشغيل iOS 10. في حالة استخدام SafeArea في xib الخاص بك ، يمكنك إضافة في viewDidLoad :

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

من المؤكد أن هناك مشكلة توافق واحدة على الأقل مع قيود منطقة الأمان في نظام التشغيل iOS 11 التي لاحظتها في Xcode 9 GM - وحدات تحكم في العرض مدفوعة بقيود منطقة آمنة.

إذا كان شريط التنقل الخاص بك مخفيًا وقمت بدفع منطقة آمنة مقيدة إلى الأعلى ، فسوف يتراكب العرض المدفوع مع شريط الحالة على نظامي iOS 9 و 10.

إذا كان شريط التنقل مرئيًا ، وتم تعطيل "تحت الأشرطة العلوية" ، فإن العرض المدفوع سيظل يتحرك أسفل شريط التنقل للوصول إلى أعلى الشاشة. يتم وضع شريط التنقل بشكل صحيح.

على نظام التشغيل iOS 11 ، سيكون التصميم صحيحًا في الحالتين.

إليك مثال بسيط: http://www.filedropper.com/foobar

وإليك مقطع فيديو من شريط w / nav مخفي (iOS 10.3 على اليسار ، iOS 11 على اليمين): https://vimeo.com/234174841/1e27a96a87

وهنا نسخة حيث شريط التنقل مرئية (تمكين في بنك الاستثمار القومي): https://vimeo.com/234316256/f022132d57

أنا قدمت هذا النحو رادار # 34477706.

بفضل @Sander للإشارة إلى حالة شريط التنقل مرئية.


هنا هو بلدي دائرة الرقابة الداخلية 9 إلى دائرة الرقابة الداخلية 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

    }

نعم ، سيعمل مشروعك / تطبيقك على إصدارات iOS قبل إصدار iOS 11 بدون أي مشكلة. في إصدارات iOS التي تسبق الإصدار 11 ، يستبدل / يأخذ في الاعتبار تخطيط المناطق الآمنة في وضع AutoLayout العادي ويتبع قواعد دليل التخطيط الأعلى والأسفل.

لقد اختبرت مشروعي الحالي مع وبدون "SafeAreaLayout" على كلا النظامين (iOS 11 و iOS 10 الخلفي). انها تعمل بشكل جيد.

فقط تأكد:

  • إذا كنت قد صممت مشروعك / واجهة المستخدم الخاصة بك في AutoLayout ؛ توجد قيود تتعلق بـ UIElement الخاص بك / بالنسبة إلى دليل التخطيط العلوي والسفلي (وليس إلى superview). لذلك ، بنقرة واحدة (تمكين) على خيار SafeAreaLayout ، سيقوم تلقائيًا بتطبيق تخطيط SafeArea بشكل صحيح لكافة ملفات Builders Interface في لوحة العمل الخاصة بك.

  • إذا كنت قد صممت مشروعك / واجهة المستخدم الخاصة بك في SafeAreaLayout ؛ ثم سيتبع تلقائيًا دليل التخطيط العلوي والسفلي في نظام iOS المتخلف.

في ما يلي عينة نموذجية مع نتيجة ، من خلال تمكين أو تعطيل تخطيط المناطق الآمنة ، لن يؤثر على التصميم الحالي.

تخطيط المناطق الآمنة:

التخطيط التلقائي

باختصار ، الإجابة على سؤالك هي: "تمكين أدلة تخطيط المناطق الآمنة المتوافقة مع نظام التشغيل iOS قبل 11"

يمكنك تنفيذ تخطيط منطقة آمنة في المشروع / التطبيق وستعمل بشكل جيد مع إصدارات iOS السابقة عن طريق تحويل تخطيط المناطق الآمنة إلى أعلى وأسفل مخطط.


تمكنت من العمل مع أدلة تخطيط المناطق الآمنة الجديدة والحفاظ على التوافق مع نظام التشغيل iOS 9 و iOS 10: (تحرير: كما هو موضح في التعليقات التي كتبهاNickEntin ، سوف يفترض هذا التنفيذ وجود شريط الحالة الحالي ، والذي لن يكون صحيحا في المشهد على iPhone X. مما يؤدي إلى مساحة كبيرة إلى الأعلى (20 نقطة).

على سبيل المثال ، إذا كنت تريد أن يكون العرض 10 نقاط أسفل شريط الحالة (و 10 نقاط أسفل مسكن المستشعر على iPhone X):

  1. في XIB الخاص بك ، انتقل إلى File Inspector وتمكين آمنة عن طريق التحقق من Use Safe Area Layout Guides .
  2. إنشاء قيد من قمة العرض إلى قمة العرض الرئيسي ، مع >= (أكبر من أو يساوي) قيد ، ثابت 30 (30 لأننا نريد تباعد 10 نقاط إلى شريط الحالة الذي يكون 20 نقطة عالية) والأولوية High (750) .
  3. أنشئ قيدًا من قمة العرض إلى أعلى منطقة آمنة ، مع القيد = (متساوي) ، ثابت 10 والأولوية Low (250).

نفس الشيء يمكن القيام به للحصول على عرض في الأسفل (وللقيادة / الزائدة أو اليسار / اليمين إلى المنطقة الآمنة):

  1. في XIB الخاص بك ، انتقل إلى File Inspector وتمكين آمنة عن طريق التحقق من Use Safe Area Layout Guides .
  2. إنشاء قيد من أسفل العرض إلى أسفل العرض الرئيسي ، مع >= (أكبر من أو يساوي) القيد ، ثابت 10 والأولوية High (750).
  3. إنشاء قيد من أسفل العرض إلى أسفل منطقة آمنة ، مع القيد = (متساوي) ، ثابت 10 والأولوية Low (250).

إذا كنت تستخدم xibs بدون لوحة القصة ، فليس لديهم أدلة تخطيط على ios 10. لذا ، انقل xib إلى لوحة العمل للحصول على التوافق مع الإصدارات السابقة.


لقد وجدت طريقة أكثر ملاءمة حيث تحتاج فقط إلى تصنيف فئة فرعية من NSLayoutConstraint مثبت على safeArea الخاص بك.

انها هراء كيندا لأن لديك للحصول على ViewController من UIView ولكن في رأيي ، وهذا بديل سهل وجيد حتى أبل في نهاية المطاف إصلاح التوافق الخلفي ل 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:


إذا كنت تريد الرمز في السويفت:

override func scrollViewDidScroll(scrollView: UIScrollView) {

    if (scrollView.contentOffset.y >= (scrollView.contentSize.height - scrollView.frame.size.height)) {
        //reach bottom
    }

    if (scrollView.contentOffset.y <= 0){
        //reach top
    }

    if (scrollView.contentOffset.y > 0 && scrollView.contentOffset.y < (scrollView.contentSize.height - scrollView.frame.size.height)){
        //not top and not bottom
    }
}




ios xcode compatibility iphone-x safearealayoutguide