Delay between animation and view accepting touch input

Hi! I was trying to add an animation to my SwiftUI view with UIKit, but after the animation runs there's a delay before the view will accept touch interactions. I thought it was because of the frame size of the view controller, but even after fixing that I still get the delay. Could anyone point me to where I might be going wrong, or if maybe using a UIKit modifier for the animation just doesn't work?

Any help would be greatly appreciated!

UIView:

class BounceView: UIView {
    required init() {
        super.init(frame: .zero)
    }
    
    func bounceAnimation() {
        guard let piece = self.subviews.first else { return }
        UIView.animate(withDuration: 0.7, delay: 0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0) {
            piece.frame.origin.x += 10
        }
    }
    
    func bounceBack() {
        guard let piece = self.subviews.first else { return }
        UIView.animate(withDuration: 0.7, delay: 0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0) {
            piece.frame.origin.x -= 10
        }
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

UIView controller:

class BounceViewController: UIViewController {
    init(controller: UIViewController) {
        super.init(nibName: nil, bundle: nil)
        
        view = BounceView()
        addChild(controller)
        controller.view.translatesAutoresizingMaskIntoConstraints = false
        controller.view.backgroundColor = .clear
        view.addSubview(controller.view)
        controller.didMove(toParent: self)
    }
    
    // adjusts view to match bounds of child
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        let subviewFrame = self.view.subviews.first?.bounds ?? .zero
        view.frame = subviewFrame
        print(subviewFrame)
        self.updateViewConstraints()
    }
    
    func update(animated: Bool) {
        let bounceView = view as? BounceView
        if animated {
            bounceView?.bounceAnimation()
        } else {
            bounceView?.bounceBack()
        }
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

SwiftUI wrapper:

struct BounceUIViewController: UIViewControllerRepresentable {
    private var controller: UIViewController
    @Binding var animated: Bool
    
    init(controller: UIViewController, animated: Binding<Bool>) {
        self.controller = controller
        self._animated = animated
    }
    
    func makeUIViewController(context: Context) -> BounceViewController {
        BounceViewController(controller: controller)
    }
    
    func updateUIViewController(_ uiViewController: BounceViewController, context: Context) {
        uiViewController.update(animated: animated)
    }
}

View extension:

extension View {
    func bounce(animated: Binding<Bool>) -> some View {
        modifier(Bounce(animated: animated))
    }
}

struct Bounce: ViewModifier {
    @Binding var animated: Bool
    init(animated: Binding<Bool>) {
        self._animated = animated
    }
    func body(content: Content) -> some View {
        BounceUIViewController(controller: content.uiViewController, animated: $animated)
    }
}
Answered by ForumsContributor in
Accepted Answer

To enable interaction during a UIView animation, pass the .interactionEnabled option to the options: parameter of the UIView.animate method. For example:

UIView.animate(withDuration: 0.7, delay: 0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0, options: .allowUserInteraction) {
    piece.frame.origin.x += 10
}
Delay between animation and view accepting touch input
 
 
Q