0

I have an Intro video section for an app. The storyboard has a segue "toMainMenu" that links to another storyboard view controller.

The IntroVideoVC has two classes inside it:-

class IntroVideoVC: UIViewController {
    var videoView: IntroVideoView!

    override func viewDidLoad() {
        videoView = IntroVideoView(controller: self)
        self.view.addSubview(videoView)

       let tap = UITapGestureRecognizer(target: self, action: #selector(tappedVideo))
       view.addGestureRecognizer(tap)
    }

    @objc func tappedVideo() {
        videoFinished();
    }

    func videoFinished() {
        self.performSegue(withIdentifier: "toMainMenu", sender: self)
    }   
}

class IntroVideoView: UIView {
    init(controller: UIViewController) {
        super.init(frame: CGRect(x: 0, y: 0, w: 0, h: 0))
        self.controller = controller
        ...
    }

    func handleVideo(videoPlayer: AVPlayer) {
        ...
        IntroVideoVC().videoFinished()
    }
}

If i tap the video it correctly performs the segue, however if i let the video end which in-turn calls IntroVideoViews -> handleVideo() method i get a crash stating it has no segue with identifier "toMainMenu".

I think i understand why but unsure how to get around the issue being new to swift. I believe it is because handleVideo() is using IntroVideoVC as a singleton and so is losing reference to IntroVideoVC's controller! I maybe (read: likely) be wrong but that is what i feel may be causing this issue.

Just looking for a nudge in the right direction

thanks in advance

rmaddy
  • 314,917
  • 42
  • 532
  • 579
teh_raab
  • 384
  • 1
  • 3
  • 21
  • 1
    `IntroVideoVC().videoFinished()`: `IntroVideoVC()` that's creating a new object, and that's not initializing it with the Storyboard. You need to do that: https://stackoverflow.com/questions/24035984/instantiate-and-present-a-viewcontroller-in-swift – Larme Jan 22 '19 at 16:05

1 Answers1

1

You could use protocol to solve that, it would be something like this:

protocol IntroVideoDelegate {
    func videoFinished()
}
class IntroVideoVC: UIViewController, IntroVideoDelegate {
    var videoView: IntroVideoView!

    override func viewDidLoad() {
        videoView = IntroVideoView(controller: self)
        videoView.videoDelegate = self
        self.view.addSubview(videoView)

       let tap = UITapGestureRecognizer(target: self, action: #selector(tappedVideo))
       view.addGestureRecognizer(tap)
    }

    @objc func tappedVideo() {
        videoFinished();
    }

    func videoFinished() {
       self.performSegue(withIdentifier: "toMainMenu", sender: self)
    }   
}

class IntroVideoView: UIView {
    videoDelegate: IntroVideoDelegate?
    init(controller: UIViewController) {
        super.init(frame: CGRect(x: 0, y: 0, w: 0, h: 0))
        self.controller = controller
        ...
    }

    func handleVideo(videoPlayer: AVPlayer) {
        ...
        videoDelegate.videoFinished()
    }
}

Remember that the videoView is still a subview to IntroVideoVC, so if the app goes back to this VC the user will see it, so if you don't want that to happen, be sure to remove it with:

videoView.removeFromSuperview()

In the videoFinished() func

If you want to do running a VC func from the view you should get the parent of IntroVideoView, here is how: Given a view, how do I get its viewController? But i'm pretty sure it breaks MVC

Eduardo Leite
  • 71
  • 1
  • 6