IOS Swift如何致命错误展开可选值

时间:2018-04-11 05:35:53

标签: swift uiviewcontroller swift4 avplayerviewcontroller

我有一个名为 BookViewC 的ViewController,它只显示1个视频。故事板包含一个名为FullName的IBOutlet和一个用于显示视频的UIView。我有功能,当你点击视频时,它应该得到下一个视频。 当我收到下一个视频时,我总是得到FullName的零值,它总能正确获得第一个视频。

  

线程1:致命错误:在展开时出乎意料地发现nil   可选值

关于全名的IBOutLet,我理解为什么,有没有办法解决这个问题?这是我的代码清理

class BookViewC: UIViewController, VideoViewDelegate{

@IBOutlet weak var VideoView: UIView!
@IBOutlet weak var FullName: UIButton!


override func viewDidLoad() {
    super.viewDidLoad()

  // This method queries the database for the latest video
  ReloadTable(Offset: 0)

}

 func reloadTable(Offset: Int) {
 // Queries the database for video name
 // Returns data in Json
        DispatchQueue.main.async {
                    for Stream in Streams! {

                        if let fullname = Stream["fullname"] as? String            {
    // This below throws the nil error when getting the 2nd video
                            self.FullName.setTitle(fullname, for: .normal)

                        }

}

   // Method below simply shows the video
   self.PlayVideo(MediaHeight: Float(pic_height), MediaURL: s_image)
  }

func PlayVideo(MediaHeight: Float, MediaURL: String) {

    let movieURL = URL(string: MediaURL)

    videoCapHeight.constant = CGFloat(MediaHeight)
    streamsModel.playerView = AVPlayer(url: movieURL!)
    streamsModel.MyAVPlayer.player = streamsModel.playerView
    streamsModel.MyAVPlayer.videoGravity = AVLayerVideoGravity.resizeAspectFill.rawValue
    streamsModel.MyAVPlayer.showsPlaybackControls = false
    streamsModel.MyAVPlayer.view.frame = VideoView.bounds
   VideoView.addSubview(streamsModel.MyAVPlayer.view)
    self.addChildViewController(streamsModel.MyAVPlayer)
    streamsModel.playerView?.isMuted = false
    streamsModel.MyAVPlayer.player?.play()
}

}

当您点按视频时,它会转到此课程

class CustomAVPLayerC: AVPlayerViewController {


    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {


            // I try to return to my original Class now
            let BookC = BookViewC()
            for touch in touches {
                let location = touch.location(in: self.view)

                if location.x <  self.view.layer.frame.size.width / 2 {
                    print("Tapped Left")
                }
                else {
                    print("Tapped Right get next video")
                // Offset is now 1 which gets the 2nd video
                   BookC.ReloadTable(offset: 1)
                }
            }



    }


}

发生的事情是,一旦我去CustomAVPLayerC控制器,BookViewC的所有IBOutlets都变为零,然后一旦我尝试返回它就会给我错误。我有什么办法可以解决这个问题或解决它吗?我显示的视频使用AVPlayer,所以点击我必须去CustomAVPLayerC控制器。任何建议都会很棒。

2 个答案:

答案 0 :(得分:2)

CommonSQLiteUtilities为零,因为IBOutlets未从BookVC初始化。使用委托模式应该可以解决问题。以下是一个可以帮助实现这一目标的例子,

创建如下协议,

.xib/storyboard

更新protocol CustomAVPLayerProtocol: class { func reloadTable(at index: Int) } 以符合BookViewC,如下所示

CustomAVPLayerProtocol

然后更新extension BookViewC: CustomAVPLayerProtocol { func reloadTable(at index: Int) { self.reloadTable(Offset: index) } }

CustomAVPLayerC

最后在class CustomAVPLayerC: AVPlayerViewController { weak var delegate: CustomAVPLayerProtocol? func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { for touch in touches { let location = touch.location(in: self.view) if location.x < self.view.layer.frame.size.width / 2 { print("Tapped Left") } else { let index = 1 self.delegate?.reloadTable(at: index) } } } } 设置BookViewC(当您初始化时)委托如下,

CustomAVPLayerC

答案 1 :(得分:1)

这些行可能会导致您的问题:

// I try to return to my original Class now
let BookC = BookViewC()

这是创建BookViewC类的 new 副本,而不是让您回到原始版本。然后,当您将其告诉reloadTable时,它背后没有任何视图可供使用。

解决此问题的方法是确保您当前的BookViewC对象(第一位代码中的this)可供视频播放器调用reloadTable方法。正常的方法是通过delegate模式。