Swift 4中如何解决动画背景遮挡界面按钮的问题?
Hey there! I see you're stuck with your animated video background blocking the 6 buttons you added via Interface Builder. Let's get those buttons visible again with two straightforward solutions.
Quickest Fix (No Extra IB Outlets Required)
The root problem here is that when you use addSublayer() to add your AVPlayerLayer to videoView's layer, this new layer gets placed on top of all existing subview layers (including the view that holds your buttons).
To fix this without needing to reference your buttons at all, just change how you insert the video layer—add it to the very bottom of videoView's layer stack instead:
- Open your
ViewController.swiftfile - In the
setupView()function, replace this line:
with:self.videoView.layer.addSublayer(newLayer)self.videoView.layer.insertSublayer(newLayer, at: 0)
This ensures the video layer sits underneath all of videoView's child views, so your buttons will automatically show up in front.
Alternative Fix (Adjusting the View Hierarchy)
If you prefer to explicitly bring your buttons to the front (maybe for clearer view hierarchy control), follow these steps:
- Open your
Main.storyboard - Locate the parent
Viewthat contains all 6 buttons (it's the child of yourVideo View) - Control-drag from this parent view into your
ViewController.swiftfile to create an IBOutlet. Name it something likebuttonsContainerView:@IBOutlet weak var buttonsContainerView: UIView! - In the
setupView()function, add this line after you set up the video layer:self.videoView.bringSubviewToFront(self.buttonsContainerView)
This will force the button container view to sit on top of all other subviews in videoView, making your buttons visible over the video.
Full Modified Code (Using the Quick Fix)
Here's your complete ViewController code with the quick fix applied, plus some safer optional binding to avoid crashes:
import UIKit import AVFoundation import AVKit class ViewController: UIViewController { @IBOutlet weak var videoView: UIView! override func viewDidLoad() { super.viewDidLoad() setupView() } private func setupView() { // Safely locate the video file without force-unwrapping guard let videoPath = Bundle.main.path(forResource: "Ocean_Waves_slow_motion_videvo", ofType: "mov"), let videoURL = URL(fileURLWithPath: videoPath) else { print("Error: Could not find the video file") return } let player = AVPlayer(url: videoURL) let playerLayer = AVPlayerLayer(player: player) playerLayer.frame = videoView.frame playerLayer.videoGravity = .resizeAspectFill // Insert video layer at the bottom of the layer stack videoView.layer.insertSublayer(playerLayer, at: 0) player.play() player.actionAtItemEnd = .none // Use the built-in notification name instead of a raw string NotificationCenter.default.addObserver( self, selector: #selector(videoDidPlayToEnd(_:)), name: .AVPlayerItemDidPlayToEndTime, object: player.currentItem ) } @objc func videoDidPlayToEnd(_ notification: Notification) { guard let playerItem = notification.object as? AVPlayerItem else { return } playerItem.seek(to: .zero) } }
Either solution should work perfectly for your setup—pick whichever feels more intuitive for your project!
内容的提问来源于stack exchange,提问作者J. Wu

