Given: UIHostingController hosted inside UIKit superview.
When: Superview transform modified before viewDidAppear. In this example moved 200pts down.
Then: Subsequent changes to superview transform will be out of sync. In this example I moved it back to its original location. Although the SwiftUI content appears to be in the correct location, hit registration is still at the orginal location, so in order to tap, I need to tap below the area it is being displayed. (see screenshot)
Xcode 12.3 - iPhone 8 Sim (iOS 14)
struct ContentView: View {
var body: some View {
Button(action: { print("Testing 123") }, label: {
Text("Button")
})
.padding()
.background(Color.gray)
}
}
class RootVC: UIViewController {
let hostingVC = UIHostingController(rootView: ContentView())
override func viewDidLoad() {
super.viewDidLoad()
hostingVC.view.translatesAutoresizingMaskIntoConstraints = false
view.translatesAutoresizingMaskIntoConstraints = false
addChild(hostingVC)
view.addSubview(hostingVC.view)
hostingVC.didMove(toParent: self)
hostingVC.view.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
hostingVC.view.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
hostingVC.view.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
hostingVC.view.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
// Start translated down before view appears
view.transform = .init(translationX: 0, y: 200)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// Move up on-appear (this would ususally happen in an animation block)
view.transform = .init(translationX: 0, y: 0)
}
}
This is a huge deal-breaker for a component-library I've been building that needs to interact with UIKit-based containers (eg: bottom sheets).
UPDATE:
I've reached out to Apple about this via their Feedback Assistant, but no response yet. A coworker of mine found a workaround that seems to fix the issue, but we have no idea why it works:
// Perform translation
containerView.transform = newTransform
swiftUISubview.layer.position.y = currentTransform.ty
containerView.setNeedsLayout()
containerView.layoutIfNeeded()