diff --git a/packages/react-native/ReactApple/RCTSwiftUI/RCTSwiftUIContainerView.swift b/packages/react-native/ReactApple/RCTSwiftUI/RCTSwiftUIContainerView.swift index 2ae423819ffb..517dc7fa057f 100644 --- a/packages/react-native/ReactApple/RCTSwiftUI/RCTSwiftUIContainerView.swift +++ b/packages/react-native/ReactApple/RCTSwiftUI/RCTSwiftUIContainerView.swift @@ -15,9 +15,10 @@ import UIKit @objc public override init() { super.init() hostingController = UIHostingController(rootView: SwiftUIContainerView(viewModel: containerViewModel)) - guard let view = hostingController?.view else { + guard let hostingController, let view = hostingController.view else { return } + Self.disableSafeArea(for: hostingController) view.backgroundColor = .clear } @@ -77,6 +78,48 @@ import UIKit containerViewModel.contrastAmount = 1 containerViewModel.hueRotationDegrees = 0 } + + private static func disableSafeArea( + for hostingController: UIHostingController + ) { + if #available(iOS 16.4, *) { + hostingController.safeAreaRegions = [] + return + } + + // Keep the pre-16.4 fallback scoped to this hosting view instance instead + // of changing SwiftUI's private hosting view class globally. + guard let hostingView = hostingController.view, + let viewClass = object_getClass(hostingView) + else { + return + } + + let subclassName = String(cString: class_getName(viewClass)) + .appending("_RCTIgnoresSafeArea") + if let viewSubclass = NSClassFromString(subclassName) { + object_setClass(hostingView, viewSubclass) + return + } + + guard let subclassNameUtf8 = (subclassName as NSString).utf8String, + let viewSubclass = objc_allocateClassPair(viewClass, subclassNameUtf8, 0), + let method = class_getInstanceMethod(UIView.self, #selector(getter: UIView.safeAreaInsets)) + else { + return + } + + let safeAreaInsets: @convention(block) (AnyObject) -> UIEdgeInsets = { _ in + return .zero + } + class_addMethod( + viewSubclass, + #selector(getter: UIView.safeAreaInsets), + imp_implementationWithBlock(safeAreaInsets), + method_getTypeEncoding(method)) + objc_registerClassPair(viewSubclass) + object_setClass(hostingView, viewSubclass) + } } class ContainerViewModel: ObservableObject {