从子视图调用UIView.animate无动画效果的原因排查
Hey there! Let's break down why this common gotcha is happening with your Swift 4 and Xcode setup—here are the most likely culprits and fixes:
1. You’re Running the Animation Off the Main Thread
UIKit requires all UI operations (including animations) to run on the main thread. If your child view controller triggers toggleWidth from a background thread (like a network request completion handler or a non-main queue closure), the animation block won’t execute—you’ll only see the final width jump without the smooth transition.
Fix: Wrap your call to toggleWidth in a main dispatch queue block:
// Inside your child view controller DispatchQueue.main.async { (self.parent as? ViewController)?.toggleWidth() }
2. Auto Layout Is Overriding Frame Changes
If your toggleWidth function directly modifies menuContainer.frame.size.width, but that view is managed by auto layout constraints, the system might immediately reset the width to match constraints. This can work from the container VC due to timing differences but fail from the child.
Better Auto Layout-Friendly Approach:
Animate the width constraint’s constant instead of tweaking the frame:
// In your container VC (ViewController) @IBOutlet weak var menuWidthConstraint: NSLayoutConstraint! // Connect this in Interface Builder func toggleWidth() { // Switch between two target widths menuWidthConstraint.constant = menuWidthConstraint.constant == 200 ? 80 : 200 UIView.animate(withDuration: 0.3) { self.view.layoutIfNeeded() // Forces the system to animate the constraint change } }
This method is reliable no matter where you call toggleWidth from, as it works with auto layout instead of against it.
3. Your Child VC’s Container Reference Is Flawed
While you said the width changes, it’s worth double-checking that your child VC is referencing the correct container instance. A weak reference that’s deallocated or incorrect casting can lead to unexpected behavior.
Proper Reference Setup:
Store a weak reference to the container VC when it’s attached:
// Child VC code weak var containerVC: ViewController? override func didMove(toParent parent: UIViewController?) { super.didMove(toParent: parent) containerVC = parent as? ViewController } // Call toggleWidth using this reference: containerVC?.toggleWidth()
4. The Animation Is Triggered Too Early in the Lifecycle
If your child VC calls toggleWidth in viewDidLoad or viewWillAppear, the container view might not be fully laid out yet, so the animation won’t render.
Fix: Trigger the animation from viewDidAppear(_:) instead:
// Child VC code override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) containerVC?.toggleWidth() }
内容的提问来源于stack exchange,提问作者crazyhor77

