如何在两个类之间传递IBOutlet?

时间:2017-02-08 04:49:20

标签: ios swift iboutlet

我有一个用于管理AVPlayerViewController的课程,显示AVPlayer。在ViewController我有3 IBOutlets

@IBOutlet weak var playButton: UIButton!
@IBOutlet weak var progressBar: UIProgressView!
@IBOutlet weak var timerLabel: UILabel!

问题是我无法弄清楚如何将IBOutletsViewController传递到我的玩家管理类。我总是得到nil

  

致命错误:在解包可选值时意外发现nil

初始化progressBartimerLabelplayButton

以下是我的播放器管理课程中的一些代码:

import UIKit
import AVFoundation

class RecordsAudioPlayer: NSObject
{
    var player = AVPlayer()
    var timerUpdateAudioProgressView = Timer()
    var timerUpdateTime = Timer()
    var isPlaying: Bool = false

...

func updateAudioProgressView()
    {
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let vc = storyboard.instantiateViewController(withIdentifier: "callRecords") as! CallRecordsViewController

        let progressBar = vc.progressBar! 
        print("method fired: updateAudioProgressView ", NSDate.init(timeIntervalSinceNow: 0).description)
        if isPlaying
        {
            let currentPlayerItem = player.currentItem
            let duration = Float((currentPlayerItem?.asset.duration.value)!)/Float((currentPlayerItem?.asset.duration.timescale)!)
            let currentTime = Float(player.currentTime().value)/Float(player.currentTime().timescale)
            progressBar.setProgress(Float(currentTime/duration), animated: false)
        }
    }

    func updateTime()
    {
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let vc = storyboard.instantiateViewController(withIdentifier: "callRecords") as! CallRecordsViewController
        let timerLabel: UILabel! = vc.timerLabel! //***I get exception here
        print("method fired: updateTime ", NSDate.init(timeIntervalSinceNow: 0).description)
        let currentTime = Int64(player.currentTime().value)/Int64(player.currentTime().timescale)
        let minutes = currentTime / 60
        let seconds = currentTime - minutes * 60
        timerLabel.text = String(format: "%02d : %02d", Int(minutes), Int(seconds))
    }

2 个答案:

答案 0 :(得分:1)

一旦加载视图,就会建立出口连接 - 这通常会延迟到呈现视图之前。

您可以通过调用vc.loadViewIfNeeded()强制执行此操作(其中vc是您的视图控制器)

但如果您的updateAudioProgressViewupdateTime的实现确实符合您的预期,那就不太可能了:他们总是创建新的视图控制器并更新其子视图/插座。这些新创建的视图控制器甚至无法显示(或者您只是跳过了演示代码)。如果您的目的是更新现有的视图控制器,则必须执行其他操作(例如,手动更改视图控制器)。

只是一句话:强烈建议你不要像你那样做。视图控制器应该是唯一一个更新它的插座的人。其他人应该只更新视图控制器的属性(如设置当前进度,时间值等),然后通知视图控制器更新自身。视图控制器将以其想要的方式更新它的出口。

答案 1 :(得分:1)

在这种情况下,代表们来救我们。为RecordsAudioPlayer类创建委托方法。并使用它们来更新进度条和计时器标签。

protocol RecordsAudioPlayerDelegate
{
  func audioplayerProgressUpdated(time:CGFloat) // change the method as your wish
}

class RecordsAudioPlayer: NSObject
{
  var delegate:RecordsAudioPlayerDelegate?
  var player = AVPlayer()
  var timerUpdateAudioProgressView = Timer()
  var timerUpdateTime = Timer()
  var isPlaying: Bool = false
    ...
    ...
    ...

  //Call the delegate method from where you get the player current time
  self.delegate.audioplayerProgressUpdated(playerTime)

  //For controlling play/pause using play button 
  func playButtonClicked()
  {
    //play/pause player based on player status
  }
}

ViewController内/创建RecordsAudioPlayer对象后委托作为自我

class YourViewController : UIViewController, RecordsAudioPlayerDelegate
{
  var recordsAudioPlayer : RecordsAudioPlayer!

  // set delegate where you create object for RecordsAudioPlayer
  self.recordsAudioPlayer.delegate = self

  //Now implement the delegate function
  func audioplayerProgressUpdated(time:CGFloat)
  {
   //update progress view and timer label
  }

  //And inside from the play button action method 
  @IBAction func playButtonClicked(sender: UIButton)
  {
   self.recordsAudioPlayer.playButtonClicked()
  }

}