When animating a frame change for a UIHostingController, the rendered View within will not animate a size change if it currently has an internal animation in progress.
Is this a known issue or should I be doing something different? I have to imagine this is a pretty common use case. I've tested this on iOS 13.3 and 14.2.
Here's a screen capture of the issue: https://www.loom.com/share/91eb220dad244c848161330b574e22df
Notice that you see the yellow UIView background during the frame animation, although you should never see it. The rendered SwiftUI View immediately changes to the final frame size and only animates the origin.
import UIKit
import SwiftUI
// When `true`, issue presents itself.
let animate = true
struct SwiftUIView: View {
@State var appeared = false
let animation = Animation
.default
.repeatForever(autoreverses: false)
var body: some View {
ZStack {
Color.pink
Image(systemName: "rays")
.resizable()
.frame(width: 50, height: 50)
.rotationEffect(appeared ? .degrees(360) : .zero)
.onAppear {
withAnimation(animation) {
if animate {
appeared = true
}
}
}
}
}
}
class ViewController: UIViewController {
var vc: UIViewController!
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .blue
view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(didTap)))
vc = UIHostingController(rootView: SwiftUIView())
vc.view.backgroundColor = .yellow
self.addChild(vc)
view.addSubview(vc.view)
vc.view.frame = CGRect(x: 50, y: 50, width: 400, height: 100)
vc.didMove(toParent: self)
}
@objc private func didTap() {
UIView.animate(withDuration: 4) {
self.vc.view.frame = CGRect(x: 300, y: 300, width: 100, height: 400)
self.view.layoutIfNeeded()
}
}
}