1 import React 2 import ExpoModulesCore 3 4 class SafeAreaProvider: ExpoView { 5 private var _currentSafeAreaInsets: UIEdgeInsets = .zero 6 private var _currentFrame: CGRect = .zero 7 private var _initialInsetsSent: Bool = false 8 let onInsetsChange = EventDispatcher() 9 10 override func safeAreaInsetsDidChange() { 11 invalidateSafeAreaInsets() 12 } 13 14 func invalidateSafeAreaInsets() { 15 guard !frame.size.equalTo(.zero) else { 16 return 17 } 18 19 let safeAreaInsets = safeAreaInsetsOrEmulate() 20 let frame = convert(bounds, to: nil) 21 22 if _initialInsetsSent && 23 DevMenuUIEdgeInsetsEqualToEdgeInsetsWithThreshold(safeAreaInsets, _currentSafeAreaInsets, 1.0 / RCTScreenScale()) && 24 frame.equalTo(_currentFrame) { 25 return 26 } 27 28 _initialInsetsSent = true 29 _currentSafeAreaInsets = safeAreaInsets 30 _currentFrame = frame 31 32 onInsetsChange([ 33 "insets": [ 34 "top": safeAreaInsets.top, 35 "right": safeAreaInsets.right, 36 "bottom": safeAreaInsets.bottom, 37 "left": safeAreaInsets.left 38 ], 39 "frame": [ 40 "x": frame.origin.x, 41 "y": frame.origin.y, 42 "width": frame.size.width, 43 "height": frame.size.height 44 ] 45 ]) 46 } 47 48 override func layoutSubviews() { 49 super.layoutSubviews() 50 invalidateSafeAreaInsets() 51 } 52 } 53