Swift 如何在页面转换期间不中断地在所有视图控制器中显示与背景相同的视频?

Swift 如何在页面转换期间不中断地在所有视图控制器中显示与背景相同的视频?,swift,Swift,Main.storyboard中有两个页面(ViewController):HomeViewController和DetailViewController 我为DetailViewController:DetailPage 我在第一页添加了一个按钮,将用户带到第二页 我还向第二页添加了一个后退按钮,将用户带回第一页 我需要在所有页面的背景中显示视频 因此,我在所有页面中添加了UIView组件来显示视频 我为每个页面中的这两个UIView组件提供了0,0,0,0约束值 首先让我分享源代码,然后我想

Main.storyboard中有两个页面(
ViewController
):
HomeViewController
DetailViewController

我为
DetailViewController
DetailPage

我在第一页添加了一个按钮,将用户带到第二页

我还向第二页添加了一个后退按钮,将用户带回第一页

我需要在所有页面的背景中显示视频

因此,我在所有页面中添加了UIView组件来显示视频

我为每个页面中的这两个UIView组件提供了0,0,0,0约束值

首先让我分享源代码,然后我想问我的问题

HomeViewController.swift
文件

import UIKit
import AVFoundation

class HomeViewController: UIViewController {

private var player: AVPlayer!

@IBOutlet weak var outlet4TheVideoUiView: UIView!
override func viewDidLoad() {
    super.viewDidLoad()
    configureVideoIssue()
}

override func viewWillAppear(_ animated: Bool) {
    configureVideoIssue()
}

func configureVideoIssue()
{
    // BACKGROUND VIDEO SCOPE STARTS
    let path  = URL(fileURLWithPath: Bundle.main.path(forResource: "clouds", ofType: "mp4")!)
    let player = AVPlayer(url: path)
    self.player = player
    let newLayer = AVPlayerLayer(player: player)

    newLayer.frame = self.view.bounds
    outlet4TheVideoUiView.frame = self.view.bounds
    outlet4TheVideoUiView.layer.addSublayer(newLayer)

    newLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill

    player.play()

    // video bitince tekrar oynatmak için
    player.actionAtItemEnd = AVPlayer.ActionAtItemEnd.none

    NotificationCenter.default.addObserver(self, selector: #selector(self.videoDidPlayToEnd(notification:)),
                                           name: NSNotification.Name(rawValue: "AVPlayerItemDidPlayToEndTimeNotification"), object: player.currentItem)

    NotificationCenter.default.addObserver(self, selector: #selector(enteredBackground), name: UIApplication.didEnterBackgroundNotification, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(enteredForeground), name: UIApplication.willEnterForegroundNotification, object: nil)
    // BACKGROUND VIDEO SCOPE ENDS
}

@objc func enteredBackground() {
    player.pause()
}

@objc func enteredForeground() {
    player.play()
}

@objc func videoDidPlayToEnd(notification: Notification)
{
    let player: AVPlayerItem = notification.object as! AVPlayerItem
    player.seek(to: .zero, completionHandler: nil)
}

@IBAction func linkBtnClick(_ sender: UIButton) {
    let controller = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "DetailPage") as! DetailViewController
    controller.modalPresentationStyle = .fullScreen
    //present(controller, animated: true, completion: nil)
    show(controller, sender: nil)
}
}
import UIKit
import AVFoundation

class DetailViewController: UIViewController {

private var player: AVPlayer!

@IBOutlet weak var outlet4TheVideoUiView: UIView!
override func viewDidLoad() {
    super.viewDidLoad()
    configureVideoIssue()
    // Do any additional setup after loading the view.
}

func configureVideoIssue()
{
    // BACKGROUND VIDEO SCOPE STARTS
    let path  = URL(fileURLWithPath: Bundle.main.path(forResource: "clouds", ofType: "mp4")!)
    let player = AVPlayer(url: path)
    self.player = player
    let newLayer = AVPlayerLayer(player: player)

    newLayer.frame = self.view.bounds
    outlet4TheVideoUiView.frame = self.view.bounds
    outlet4TheVideoUiView.layer.addSublayer(newLayer)

    newLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill

    player.play()

    // video bitince tekrar oynatmak için
    player.actionAtItemEnd = AVPlayer.ActionAtItemEnd.none

    NotificationCenter.default.addObserver(self, selector: #selector(self.videoDidPlayToEnd(notification:)),
                                           name: NSNotification.Name(rawValue: "AVPlayerItemDidPlayToEndTimeNotification"), object: player.currentItem)

    NotificationCenter.default.addObserver(self, selector: #selector(enteredBackground), name: UIApplication.didEnterBackgroundNotification, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(enteredForeground), name: UIApplication.willEnterForegroundNotification, object: nil)
    // BACKGROUND VIDEO SCOPE ENDS
}

@objc func enteredBackground() {
    player.pause()
}

@objc func enteredForeground() {
    player.play()
}

@objc func videoDidPlayToEnd(notification: Notification)
{
    let player: AVPlayerItem = notification.object as! AVPlayerItem
    player.seek(to: .zero, completionHandler: nil)
}

@IBAction func btnBackClick(_ sender: UIButton) {
    dismiss(animated: true, completion: nil)
}
}
DetailViewController.swift
文件

import UIKit
import AVFoundation

class HomeViewController: UIViewController {

private var player: AVPlayer!

@IBOutlet weak var outlet4TheVideoUiView: UIView!
override func viewDidLoad() {
    super.viewDidLoad()
    configureVideoIssue()
}

override func viewWillAppear(_ animated: Bool) {
    configureVideoIssue()
}

func configureVideoIssue()
{
    // BACKGROUND VIDEO SCOPE STARTS
    let path  = URL(fileURLWithPath: Bundle.main.path(forResource: "clouds", ofType: "mp4")!)
    let player = AVPlayer(url: path)
    self.player = player
    let newLayer = AVPlayerLayer(player: player)

    newLayer.frame = self.view.bounds
    outlet4TheVideoUiView.frame = self.view.bounds
    outlet4TheVideoUiView.layer.addSublayer(newLayer)

    newLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill

    player.play()

    // video bitince tekrar oynatmak için
    player.actionAtItemEnd = AVPlayer.ActionAtItemEnd.none

    NotificationCenter.default.addObserver(self, selector: #selector(self.videoDidPlayToEnd(notification:)),
                                           name: NSNotification.Name(rawValue: "AVPlayerItemDidPlayToEndTimeNotification"), object: player.currentItem)

    NotificationCenter.default.addObserver(self, selector: #selector(enteredBackground), name: UIApplication.didEnterBackgroundNotification, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(enteredForeground), name: UIApplication.willEnterForegroundNotification, object: nil)
    // BACKGROUND VIDEO SCOPE ENDS
}

@objc func enteredBackground() {
    player.pause()
}

@objc func enteredForeground() {
    player.play()
}

@objc func videoDidPlayToEnd(notification: Notification)
{
    let player: AVPlayerItem = notification.object as! AVPlayerItem
    player.seek(to: .zero, completionHandler: nil)
}

@IBAction func linkBtnClick(_ sender: UIButton) {
    let controller = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "DetailPage") as! DetailViewController
    controller.modalPresentationStyle = .fullScreen
    //present(controller, animated: true, completion: nil)
    show(controller, sender: nil)
}
}
import UIKit
import AVFoundation

class DetailViewController: UIViewController {

private var player: AVPlayer!

@IBOutlet weak var outlet4TheVideoUiView: UIView!
override func viewDidLoad() {
    super.viewDidLoad()
    configureVideoIssue()
    // Do any additional setup after loading the view.
}

func configureVideoIssue()
{
    // BACKGROUND VIDEO SCOPE STARTS
    let path  = URL(fileURLWithPath: Bundle.main.path(forResource: "clouds", ofType: "mp4")!)
    let player = AVPlayer(url: path)
    self.player = player
    let newLayer = AVPlayerLayer(player: player)

    newLayer.frame = self.view.bounds
    outlet4TheVideoUiView.frame = self.view.bounds
    outlet4TheVideoUiView.layer.addSublayer(newLayer)

    newLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill

    player.play()

    // video bitince tekrar oynatmak için
    player.actionAtItemEnd = AVPlayer.ActionAtItemEnd.none

    NotificationCenter.default.addObserver(self, selector: #selector(self.videoDidPlayToEnd(notification:)),
                                           name: NSNotification.Name(rawValue: "AVPlayerItemDidPlayToEndTimeNotification"), object: player.currentItem)

    NotificationCenter.default.addObserver(self, selector: #selector(enteredBackground), name: UIApplication.didEnterBackgroundNotification, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(enteredForeground), name: UIApplication.willEnterForegroundNotification, object: nil)
    // BACKGROUND VIDEO SCOPE ENDS
}

@objc func enteredBackground() {
    player.pause()
}

@objc func enteredForeground() {
    player.play()
}

@objc func videoDidPlayToEnd(notification: Notification)
{
    let player: AVPlayerItem = notification.object as! AVPlayerItem
    player.seek(to: .zero, completionHandler: nil)
}

@IBAction func btnBackClick(_ sender: UIButton) {
    dismiss(animated: true, completion: nil)
}
}
第一个问题:我确信它不应该是这样,因为两个ViewController中编写的代码相同。那么我该如何避免这种情况呢?有什么建议吗?我应该使用相同的视频ui视图对象作为所有视图控制器的背景。这有意义吗?如果没有意义。我该怎么办?例如,我在
visualstudio
中使用
asp.net
user control
组件来实现这个场景。我创建了一个视频组件(用户控件),可以将该组件用作所有页面的背景

第二个问题:(如果我们无法找到第一个问题的解决方案),让我们假设应用程序用户现在看到了主页。假设用户在10秒后点击按钮查看第二页(详细页)。按钮点击操作将用户带到第二页,但视频从第一秒开始。视频应从第10秒或第11秒开始继续播放。我该怎么做

第三个问题:单击第一页中的按钮后,第二页从底部开始。第二页是否会随第一页淡出动画而出现第二页动画

重要细节:视频应在应用程序最小化后停止,并在应用程序用户最大化应用程序后继续。其他重要的细节是:按钮不在视频视图内。用户可以通过这种方式看到视频上方的按钮。让我以图像的顺序显示组件的层:


一种方法是在
根窗口上设置视图,然后将所有视图的背景色设置为清除

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    // Override point for customization after application launch.

    let window=self.window!
    backgroundVideoView.bounds = window.bounds
    window.addSubview(backgroundVideoView)
    playVideo()

    return true
}
此处,
backgroundVideoView
指将播放您的视频的视图


不过,我必须警告您,这将消耗大量内存,但会让您获得所需的行为。

在post得到回复之前,我一直在尝试自己解决这个问题。我这样做了:我创建了一个基本UIViewController文件。然后我在这个文件中添加了所有这些视频内容。然后由BaseViewController继承DetailViewController和HomeViewController..等。这也会消耗大量内存吗@上述解决方案(添加BaseViewController和继承问题)只解决了第一个问题。在页面转换过程中,我如何解决第二个和第三个问题?亲爱的@Nothing您能扩展您的解决方案吗?我需要背景视频视图的清晰细节。谢谢。如果在根窗口中添加,您将不会出现第二个和第三个问题的场景。一定要试一下。