在 iPhone X 上,UIView 中的 safeAreaInsets 为 0。

82

我正在更新我的应用以适应iPhone X。除了一个视图,所有视图都运行良好。 我有一个视图控制器,它呈现一个自定义的UIView,覆盖整个屏幕。 之前我使用UIScreen.main.bounds在所有布局完成之前找到视图的大小(我需要为collectionView放置正确的itemSize),但现在我想做一些类似于UIScreen.main.bounds.size.height - safeAreaInsets.bottom 的操作来获取正确的可用空间大小。问题是,在iPhone X(模拟器)上尝试时,safeAreaInsets返回(0,0,0,0)。有什么想法吗? 在其他视图中,我得到了正确的safeAreaInsets数字。

谢谢!


4
无论何时何地,您都可以使用以下代码:if #available(iOS 11.0, tvOS 11.0, *) { return UIApplication.shared.delegate?.window??.safeAreaInsets != .zero } return falseSOURCE - Cœur
根据下面 Mars 的回答,我也发现唯一可靠的方法是在 viewDidLayoutSubviews() 或 viewDidAppear 中获取这些值。实际上,"override func viewSafeAreaInsetsDidChange()" 似乎是最好的选择。 - David H
14个回答

1

只需尝试使用self.view.safeAreaInsets替代UIApplication.shared.keyWindow?.safeAreaInsets。当通过应用程序keyWindow请求时,安全区域嵌入似乎在iOS 11.x.x设备上无法填充。


1

要计算安全区域的 safeAreaInsets,请尝试在 viewWillAppear() 中获取它,因为在 didLoad() 中视图尚未形成。 您将在 willAppear() 中获得正确的插入值!


1
[UIApplication sharedApplication].keyWindow.safeAreaInsets return none zero

0
如果您无法进行子类化,您可以使用此 UIView 扩展程序。
它为您提供了以下 API:
view.onSafeAreaInsetsDidChange = { [unowned self] in
   self.updateSomeLayout()
}

该扩展使用对象关联添加了一个名为onSafeAreaInsetsDidChange的属性。然后,它会交换UIView.safeAreaInsetsDidChange()方法以调用闭包(如果有)。
extension UIView {
    
    typealias Action = () -> Void
    
    var onSafeAreaInsetsDidChange: Action? {
        get {
            associatedObject(for: "onSafeAreaInsetsDidChange") as? Action
        }
        set {
            Self.swizzleSafeAreaInsetsDidChangeIfNeeded()
            set(associatedObject: newValue, for: "onSafeAreaInsetsDidChange")
        }
    }
    
    static var swizzled = false
    
    static func swizzleSafeAreaInsetsDidChangeIfNeeded() {
        guard swizzled == false else { return }
        swizzle(
            method: "safeAreaInsetsDidChange",
            originalSelector: #selector(originalSafeAreaInsetsDidChange),
            swizzledSelector: #selector(swizzledSafeAreaInsetsDidChange),
            for: Self.self
        )
        swizzled = true
    }
    
    @objc func originalSafeAreaInsetsDidChange() {
        // Original implementaion will be copied here.
    }
    
    @objc func swizzledSafeAreaInsetsDidChange() {
        originalSafeAreaInsetsDidChange()
        onSafeAreaInsetsDidChange?()
    }
}

它使用了一些助手(参见 NSObject+Extensions.swiftNSObject+Swizzle.swift),但如果您直接使用 sizzling 和对象关联的 API,则不真正需要它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接