Я продолжаю использовать один и тот же кусок кода снова и снова.Как мне это закрепить? - PullRequest
0 голосов
/ 10 октября 2018

Будучи новичком Свифта, я копирую и вставляю код.Я знаю, что должен использовать метод СУХОЙ, а не делать это, но этот конкретный фрагмент кода поставил меня в тупик.Я попытался создать структуру, чтобы удержать ее, но структура породила всевозможные ошибки.Я не совсем понимаю классы и то, как бы я их подкласс, и, возможно, это решение.Я просто не знаю, как это сделать?Или, может быть, расширение?

В любом случае, вот код, который я продолжаю копировать и вставлять в каждый новый контроллер представления:

import UIKit
import AVKit

class Step3JobSummaryVC: UIViewController, UITableViewDataSource, UITableViewDelegate {

...

var sourceVCIdentity = "setup"

var initialLaunch = true
let playerVC = AVPlayerViewController()
let video = Video.step3JobsSummary

...


// ------------------------
// Autoplay Video Functions
// ------------------------

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    if initialLaunch == true {
        showUnplayedVideo()
        initialLaunch = false
    }

    Video.updatePlaybackTime(playerVC: playerVC, videoURL: video.url, firebaseVideoID: video.firebaseID)
}

func showUnplayedVideo() {

    // 1. get current video data
    Video.getFirebaseData(firebaseVideoID: video.firebaseID) { (playbackTime, watched) in

        if !watched {

            // 2. show setup video popup on first load
            guard let videoURL = URL(string: self.video.url) else { print("url error"); return }
            let player = AVPlayer(url: videoURL)

            self.playerVC.player = player

            // 3. fast forward to where user left off (if applicable)
            player.seek(to: CMTimeMakeWithSeconds(playbackTime, 1))

            // 4. dismiss the player once the video is over and update Firebase
            NotificationCenter.default.addObserver(self,
                                                   selector: #selector(self.playerDidFinishPlaying),
                                                   name: NSNotification.Name.AVPlayerItemDidPlayToEndTime,
                                                   object: self.playerVC.player?.currentItem)

            self.present(self.playerVC, animated: true) {
                self.playerVC.player?.play()
            }
        }
    }
}

@objc func playerDidFinishPlaying(note: NSNotification) {
    self.playerVC.dismiss(animated: true)
    Video.updateFirebase(firebaseVideoID: video.firebaseID)
}

Любая помощь будет полезна.Я просто пытаюсь узнать: -)

РЕДАКТИРОВАТЬ # 1

Это моя попытка расширения.Я упростил и реорганизовал свой код, но, как и прежде, он выдает ошибку.На этот раз ошибка «расширения не должны содержать хранимых свойств».Так как мне получить доступ к AVPlayerController?!?

extension UIViewController {

let playerVC = AVPlayerViewController()

func showUnplayedVideo(video: Video) {

    // 1. get current video data
    Video.getFirebaseData(firebaseVideoID: video.firebaseID) { (playbackTime, watched) in

        if !watched {
            // 2. show setup video popup on first load
            guard let videoURL = URL(string: video.url) else { print("url error"); return }
            let player = AVPlayer(url: videoURL)

            self.playerVC.player = player

            // 3. fast forward to where user left off (if applicable)
            player.seek(to: CMTimeMakeWithSeconds(playbackTime, 1))

            // 4. dismiss the player once the video is over and update Firebase
            NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime,
                                                   object: playerVC.player?.currentItem,
                                                   queue: .main) { (notification) in

                                                    self.playerDidFinishPlaying(note: notification as NSNotification)

            self.present(self.playerVC, animated: true) {
                self.playerVC.player?.play()
            }
        }
    }
}

    func playerDidFinishPlaying(note: NSNotification, video: Video) {
        self.playerVC.dismiss(animated: true)
        Video.updateFirebase(firebaseVideoID: video.firebaseID)
    }
}

EDIT # 2

Итак, я получил код для компиляции без каких-либо ошибок, но теперь он не запускается,Аааа.

extension UIViewController {

func showUnplayedVideo(playerVC: AVPlayerViewController, video: Video) {

    print("does this code even fire?")

    // 1. get current video data
    Video.getFirebaseData(firebaseVideoID: video.firebaseID) { (playbackTime, watched) in

        if !watched {
            // 2. show setup video popup on first load
            guard let videoURL = URL(string: video.url) else { print("url error"); return }
            let player = AVPlayer(url: videoURL)

            playerVC.player = player

            // 3. fast forward to where user left off (if applicable)
            player.seek(to: CMTimeMakeWithSeconds(playbackTime, 1))

            // 4. dismiss the player once the video is over and update Firebase
            NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime,
                                                   object: playerVC.player?.currentItem,
                                                   queue: .main) { (notification) in

                                                    self.playerDidFinishPlaying(playerVC: playerVC, note: notification as NSNotification, video: video)

                                                    self.present(playerVC, animated: true) {
                                                        playerVC.player?.play()
                                                    }
            }
        }
    }
}

func playerDidFinishPlaying(playerVC: AVPlayerViewController, note: NSNotification, video: Video) {
    playerVC.dismiss(animated: true)
    Video.updateFirebase(firebaseVideoID: video.firebaseID)
}
}

Почему это не сработает?

Ответы [ 3 ]

0 голосов
/ 10 октября 2018

Я бы начал с определения протокола для вашей функциональности примерно так:

protocol VideoPlayable {
    func showUnplayedVideo(playerVC: AVPlayerViewController, video: Video)
}

А затем добавил бы к нему реализацию по умолчанию

extension VideoPlayable where Self: UIViewController {

    func showUnplayedVideo(playerVC: AVPlayerViewController, video: Video) {

       print("does this code even fire?")

       // 1. get current video data
       Video.getFirebaseData(firebaseVideoID: video.firebaseID) { (playbackTime, watched) in

            if !watched {
            // 2. show setup video popup on first load
                guard let videoURL = URL(string: video.url) else { print("url error"); return }
                let player = AVPlayer(url: videoURL)

                playerVC.player = player

                // 3. fast forward to where user left off (if applicable)
                player.seek(to: CMTimeMakeWithSeconds(playbackTime, 1))

                // 4. dismiss the player once the video is over and update Firebase
                NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime,
                                                   object: playerVC.player?.currentItem,
                                                   queue: .main) { (notification) in

                    self.playerDidFinishPlaying(playerVC: playerVC, note: notification as NSNotification, video: video)

                }

                self.present(playerVC, animated: true) {
                    playerVC.player?.play()
                }

            }
        }
    }

    private func playerDidFinishPlaying(playerVC: AVPlayerViewController, note: NSNotification, video: Video) {
        playerVC.dismiss(animated: true)
        Video.updateFirebase(firebaseVideoID: video.firebaseID)
    }
}

Благодаря этому, когда вы добавляетеVideoPlayable протокол к контроллеру у вас будут доступны ваши пользовательские функции, а другие контроллеры, которые не должны иметь эти функции, не будут иметь доступа к этому методу.Также, если вы действительно хотите иметь доступ к методу

func playerDidFinishPlaying(playerVC: AVPlayerViewController, note: NSNotification, video: Video)

Добавьте его в протокол и удалите личное утверждение из реализации.

А ваш видеопроигрыватель не показывался, потому чтоВы добавили представление игрока в блок уведомлений.

Также рассмотрите возможность добавления правильной самообработки в свои блоки.Прямо сейчас я думаю, что возможно, что self может быть поймано в блоках.

Просто чтобы сообщить вам утверждение, где Self: UIViewController Ограничивает доступ реализации к UIViewControllers, поэтому, если вы добавляете протокол кПодкласс UIView, вы не получите доступ к реализации по умолчанию.Затем вам нужно будет добавить новый :), это предотвратит пропадание протокола в тех местах, где вы не хотите его использовать.

0 голосов
/ 10 октября 2018

Вы можете просто переместить весь повторно используемый код в отдельный класс:

class Step3JobSummaryVC: UIViewController {

    let videoPlayer = VideoPlayer(video: Video.step3JobsSummary)

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        videoPlayer.start(on: self)
    }
}

final
class VideoPlayer {
    private var initialLaunch: Bool = true
    private let playerVC = AVPlayerViewController()
    private let video: Video

    init(video: Video) {
        self.video = video
    }

    func start(on viewController: UIViewController) {
        if initialLaunch == true {
            showUnplayedVideo(on: viewController)
            initialLaunch = false
        }

        Video.updatePlaybackTime(playerVC: playerVC, videoURL: video.url, firebaseVideoID: video.firebaseID)
    }

    func showUnplayedVideo(on viewController: UIViewController) {

        // 1. get current video data
        Video.getFirebaseData(firebaseVideoID: video.firebaseID) { (playbackTime, watched) in

            if !watched {

                // 2. show setup video popup on first load
                guard let videoURL = URL(string: self.video.url) else { print("url error"); return }
                let player = AVPlayer(url: videoURL)

                self.playerVC.player = player

                // 3. fast forward to where user left off (if applicable)
                player.seek(to: CMTimeMakeWithSeconds(playbackTime, preferredTimescale: 1))

                // 4. dismiss the player once the video is over and update Firebase
                NotificationCenter.default.addObserver(self,
                                                       selector: #selector(self.playerDidFinishPlaying),
                                                       name: NSNotification.Name.AVPlayerItemDidPlayToEndTime,
                                                       object: self.playerVC.player?.currentItem)

                viewController.present(self.playerVC, animated: true) {
                    self.playerVC.player?.play()
                }
            }
        }
    }

    @objc func playerDidFinishPlaying(note: NSNotification) {
        self.playerVC.dismiss(animated: true)
        Video.updateFirebase(firebaseVideoID: video.firebaseID)
    }
}
0 голосов
/ 10 октября 2018

Рассматривали ли вы использование более традиционной модели наследования?

class VideoPlayingBaseController: : UIViewController, UITableViewDataSource, UITableViewDelegate {

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    if initialLaunch == true {
        showUnplayedVideo()
        initialLaunch = false
    }

    Video.updatePlaybackTime(playerVC: playerVC, videoURL: video.url, firebaseVideoID: video.firebaseID)
}

func showUnplayedVideo() {

    // 1. get current video data
    Video.getFirebaseData(firebaseVideoID: video.firebaseID) { (playbackTime, watched) in

        if !watched {

            // 2. show setup video popup on first load
            guard let videoURL = URL(string: self.video.url) else { print("url error"); return }
            let player = AVPlayer(url: videoURL)

            self.playerVC.player = player

            // 3. fast forward to where user left off (if applicable)
            player.seek(to: CMTimeMakeWithSeconds(playbackTime, 1))

            // 4. dismiss the player once the video is over and update Firebase
            NotificationCenter.default.addObserver(self,
                                                   selector: #selector(self.playerDidFinishPlaying),
                                                   name: NSNotification.Name.AVPlayerItemDidPlayToEndTime,
                                                   object: self.playerVC.player?.currentItem)

            self.present(self.playerVC, animated: true) {
                self.playerVC.player?.play()
            }
        }
    }
}

@objc func playerDidFinishPlaying(note: NSNotification) {
    self.playerVC.dismiss(animated: true)
    Video.updateFirebase(firebaseVideoID: video.firebaseID)
}


}

Тогда попросите ваших классов, которые ее используют:

class Step3JobSummaryVC: VideoPlayingBaseController {
 //more code here
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...