代码之家  ›  专栏  ›  技术社区  ›  Tiago Lira

xib文件中的安全区域布局指南-iOS 10

  •  68
  • Tiago Lira  · 技术社区  · 7 年前

    我开始为iPhone X修改我的应用程序,并在界面生成器中发现了一个问题。

    但在我的XIB文件中,iOS 10不遵守安全区域布局指南。

    它们在新的操作系统版本中运行良好,但iOS 10设备似乎只是假设安全区域距离为零(忽略状态栏大小)。

    我是否缺少任何必需的配置?这是一个Xcode错误吗?如果是的话,有什么已知的解决方法吗?

    以下是测试项目中问题的屏幕截图(左iOS 10,右iOS 11):

    safe area alignment on top of the screen

    9 回复  |  直到 7 年前
        1
  •  71
  •   clarus    7 年前

    here .

    如果采用这种方法,则需要将每个文件设置为将在(iOS 11或更早版本)上使用的正确部署目标,以便Xcode不会向您发出警告,并允许您使用布局指南或安全区域,具体取决于。在代码中,在运行时检查iOS 11,然后加载适当的故事板/XIB。

    这种方法的缺点是维护(你将有两套视图控制器来维护和保持同步),但一旦你的应用程序只支持iOS 11+或Apple修复了向后兼容性布局指南约束生成,你就可以摆脱iOS 11之前的版本。

    顺便问一下,你是如何显示你所看到的控制器的?它只是根视图控制器还是您演示了它,或者。。?我注意到的问题与推送视图控制器有关,因此您可能遇到了另一种情况。

        2
  •  14
  •   Martin Massera    6 年前

    • 对于ios 11: view.top == safe area.top
    • view.top == superview.top + 20

    将它们作为插座添加为 myConstraintSAFEAREA myConstraintSUPERVIEW 分别地然后:

    override func viewDidLoad() {
        if #available(iOS 11.0, *) {
            view.removeConstraint(myConstraintSUPERVIEW)
        } else {
            view.removeConstraint(myConstraintSAFEAREA)
        }
    }
    
        3
  •  6
  •   Falco Winkler    6 年前

    对我来说,让它在两个版本上都工作的一个简单的修复方法是

        if #available(iOS 11, *) {}
        else {
            self.edgesForExtendedLayout = []
        }
    

    因此,将它们设置为空数组可以确保视图控制器执行此操作 延伸至导航条下方。

    here

        4
  •  3
  •   Tumata    6 年前

    我将本页中的一些答案合并到这个页面中,这个页面很有魅力(根据问题的要求,仅适用于顶部布局指南):

    1. 确保在故事板或xib文件中使用安全区域
    2. 对于每个 view 它有一个 constraint 连接到安全区域。顶部
      • 看法
      • 限制
    3. 打开ViewController内部 viewDidLoad:

      if (@available(iOS 11.0, *)) {}
      else {
          // For each view and constraint do:
          [self.view.topAnchor constraintEqualToAnchor:self.topLayoutGuide.bottomAnchor].active = YES;
          self.constraint.active = NO;
      }
      

    @property (strong, nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray *constraintsAttachedToSafeAreaTop;
    @property (strong, nonatomic) IBOutletCollection(UIView) NSArray *viewsAttachedToSafeAreaTop;
    
    
    if (@available(iOS 11.0, *)) {}
    else {
        for (UIView *viewAttachedToSafeAreaTop in self.viewsAttachedToSafeAreaTop) {
            [viewAttachedToSafeAreaTop.topAnchor constraintEqualToAnchor:self.topLayoutGuide.bottomAnchor].active = YES;
        }
        for (NSLayoutConstraint *constraintAttachedToSafeAreaTop in self.constraintsAttachedToSafeAreaTop) {
            constraintAttachedToSafeAreaTop.active = NO;
        }
    }
    

    每个IBMoutletCollection的计数应该相等。e、 g.对于每个视图 应该有其相关的约束

        5
  •  0
  •   Jonny    7 年前

    我最终删除了我在xib文件中对安全区域的约束。 相反,我在viewDidLayoutSubviews中创建了一个到所讨论的UIView的出口,并从代码中这样连接它。

    let constraint = alert.viewContents.topAnchor.constraint(equalTo: self.topLayoutGuide.bottomAnchor, constant: 0)
    constraint.priority = 998
    constraint.isActive = true
    

    简单且一次性的解决方案。如果有什么东西坏了,我会回来的。

        6
  •  0
  •   Menan Vadivel    6 年前

    override func viewDidLoad() {
        super.viewDidLoad()
    
        if #available(iOS 11.0, *) {}
        else {
            view.heightAnchor.constraint(equalToConstant: UIScreen.main.bounds.height - 80).isActive = true
            view.widthAnchor.constraint(equalToConstant: UIScreen.main.bounds.width - 20).isActive = true
        }
    }
    
        7
  •  0
  •   Alex Brown    6 年前

    我添加了一个NSLayoutConstraint子类来解决这个问题( IBAdjustableConstraint @IBInspectable 变量,如下所示。

    class IBAdjustableConstraint: NSLayoutConstraint {
    
        @IBInspectable var safeAreaAdjustedConstant: CGFloat = 0 {
            didSet {
                if OS.TenOrBelow {
                    constant += safeAreaAdjustedConstantLegacy
                }
            }
        }
    }
    

    OS.TenOrBelow

    struct OS {
        static let TenOrBelow = UIDevice.current.systemVersion.compare("10.9", options: NSString.CompareOptions.numeric) == ComparisonResult.orderedAscending
    }
    

    只需将其设置为IB中约束的子类,就可以生成<iOS11具体变更。希望这对别人有帮助。

        8
  •  0
  •   Suraj Rao Raas Masood    6 年前

    @IBOutlet weak var topConstraint : NSLayoutConstraint!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        if !DeviceType.IS_IPHONE_X {
            if #available(iOS 11, *)  {
            }
            else{
                topConstraint.constant = 20
            }
        }
    }
    
        9
  •  -5
  •   Vyachaslav Gerchicov    7 年前

    找到了最简单的解决方案-只需禁用 safe area 和使用 topLayoutGuide bottomLayoutGuide +为iPhone X添加补丁。也许这不是一个漂亮的解决方案,但需要尽可能少的努力