2017-02-08 5 views
0

Ich habe eine Klasse für die Verwaltung AVPlayer und ViewController zeigt AVPlayer. In ViewController habe ich 3 IBOutlets:Wie übergebe ich IBOutlet zwischen zwei Klassen?

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

Das Problem ist, ich kann nicht herausfinden, wie IBOutlets von ViewController auf meine Player Verwaltung Klasse zu übergeben. Ich bekomme immer nil und

fatal error: unexpectedly found nil while unwrapping an Optional value

wenn progressBar, timerLabel oder playButton initialisiert.

Hier ist ein Code von meiner Player Verwaltung Klasse:

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)) 
    } 

Antwort

1

In diesem Fall kamen Delegierte für unsere Rettung. Erstellen Sie Delegate-Methoden für Ihre Klasse RecordsAudioPlayer. Und verwenden Sie sie, um Fortschrittsbalken und Timer-Label zu aktualisieren.

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 
    } 
} 

Und in Ihrem ViewController während/nach dem Erstellen RecordsAudioPlayer Objekt gesetzt Delegat als selbst

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() 
    } 

} 
1

Outlet-Verbindungen so schnell etablieren wie die Ansicht geladen wird - und das ist in der Regel, bis die latenten Ansicht wird präsentiert.

Sie können dies durch vc.loadViewIfNeeded() Aufruf erzwingen (wo vc ist Ihr View-Controller)

Aber nicht ganz shure, wenn Ihre Implementierung von updateAudioProgressView und updateTime wirklich tun, was Sie erwarten: Sie schaffen immer neue View-Controller und Update ihre Subviews/Outlets. Diese neu erstellten View-Controller werden nicht einmal angezeigt (oder Sie haben den Präsentationscode einfach übersprungen). Wenn Sie einen vorhandenen View-Controller aktualisieren möchten, müssen Sie etwas anderes tun (z. B. den View-Controller zur Aktualisierung mitgeben).

Und nur eine Bemerkung: Es wird dringend empfohlen, dass Sie die Dinge nicht so machen, wie Sie es tun. Der View-Controller sollte der einzige sein, der seine Outlets aktualisiert. Jeder andere sollte nur die Eigenschaften des View-Controllers aktualisieren (z. B. den aktuellen Fortschritt, den Zeitwert usw. einstellen) und dann den View-Controller darüber informieren, dass er sich selbst aktualisiert. Der View-Controller aktualisiert dann seine Präsentationen so, wie er es möchte.

+0

Vielen Dank für Ihre Antwort. Sie haben definitiv nicht das, was ich erwartet habe. Ihre Empfehlungen sind sehr nützlich. Ich werde diese Klasse mit ihnen neu schreiben. Was meinen aktuellen Code betrifft, sollte ich 'vc.loadViewIfNeeded()' in meinen Funktionen oder woanders verwenden? Ich bekomme immer noch die selbe Ausnahme – BadCodeDeveloper

Verwandte Themen