【问题标题】:How to pass IBOutlet between two classes?如何在两个类之间传递 IBOutlet?
【发布时间】:2017-02-08 04:49:20
【问题描述】:

我有一个管理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))
    }

【问题讨论】:

    标签: ios swift iboutlet


    【解决方案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()
      }
    
    }
    

    【讨论】:

      【解决方案2】:

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

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

      但如果你的updateAudioProgressViewupdateTime 的实现真的如你所愿:他们总是创建 视图控制器并更新他们的子视图/出口。这些新创建的视图控制器甚至不会显示(或者您只是跳过了演示代码)。如果您的意图是更新现有的视图控制器,则必须执行其他操作(例如,提交要更新的视图控制器)。

      还有一句话:强烈建议您不要按照自己的方式做事。视图控制器应该是唯一更新其出口的控制器。其他任何人都应该只更新视图控制器的属性(例如设置当前进度、时间值等),然后通知视图控制器进行自我更新。然后,视图控制器将按照自己想要的方式更新它的呈现方式。

      【讨论】:

      • 感谢您的回答。他们绝对不符合我的预期。您的建议非常有用,我将使用它们重写本课程。至于我当前的代码,我应该在我的函数中还是在其他地方使用vc.loadViewIfNeeded()?我仍然遇到同样的异常
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多