BaseController委托不在标签栏控制器内的所有继承视图控制器中工作

时间:2016-12-22 16:04:16

标签: ios swift avplayer

我很难理解为什么我的代理在基本控制器中定义的不在继承的视图控制器中工作。

我有一个TabBarController,它有2个ViewControllers。每个ViewController都是BaseController的子类。

BaseController实现委托并更新标签视图。

当我启动应用程序并单击“播放”时,FirstVC会更新标签,但是当我将标签切换到SecondVC时,它会开始更新,但是当我再次单击FirstVC时,更新会卡住并且不会更新标签,但标签会不断更新在SecondVC。

import Foundation
import AVFoundation

protocol SharedPlayerNotificaions : class {

    func willPlay(status: Bool)
    func currentPlayTime(timeString: String)
}

class SharedPlayer : NSObject {

    static let sharedInstance = SharedPlayer()    
    private var player : AVPlayer?
    weak var delegate : SharedPlayerNotificaions?

    override private init() {
        super.init()
        player = AVPlayer()

    }

    override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
        if keyPath == "status" {

            if player?.status == AVPlayerStatus.Unknown {
                delegate?.willPlay(false)
            }
            if player?.status == AVPlayerStatus.Failed {
                print("failed")
                delegate?.willPlay(false)
            }

            if player?.status == AVPlayerStatus.ReadyToPlay {
                print("readytoplay")
                delegate?.willPlay(true)
            }
        }
        if keyPath == "rate" {
        }
        if keyPath == "duration" {   
        }
    }

    func play(){

        player?.play()
        let interval = CMTime(value: 1, timescale: 2)
        player?.addPeriodicTimeObserverForInterval(interval, queue: dispatch_get_main_queue(), usingBlock: { (progressTime) in
            let seconds = CMTimeGetSeconds(progressTime)
            let secondsString = String(format: "%02d", Int(seconds % 60))
            let minutesString = String(format: "%02d", Int(seconds / 60))
            self.delegate?.currentPlayTime("\(minutesString):\(secondsString)")
        })
    }

    func setUrl(urlString: String){

        if let url = NSURL(string: urlString){
            player = AVPlayer(URL: url)
            player?.addObserver(self, forKeyPath: "status", options: NSKeyValueObservingOptions.New, context: nil)
             player?.addObserver(self, forKeyPath: "rate", options: NSKeyValueObservingOptions.New, context: nil)
             player?.addObserver(self, forKeyPath: "duration", options: NSKeyValueObservingOptions.New, context: nil)
        }
    }
}

BaseController

    class BaseController : UIViewController, SharedPlayerNotificaions {

        let label = UILabel()

        override func viewDidLoad() {

            SharedPlayer.sharedInstance.delegate = self

            view.addSubview(label)
            label.translatesAutoresizingMaskIntoConstraints = false
            view.addConstraint(NSLayoutConstraint(item: label, attribute: .Left, relatedBy: .Equal, toItem: view, attribute: .Left, multiplier: 1, constant: 10))
            view.addConstraint(NSLayoutConstraint(item: label, attribute: .Width, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: 50))
            view.addConstraint(NSLayoutConstraint(item: label, attribute: .Top, relatedBy: .Equal, toItem: view, attribute: .Top, multiplier: 1, constant: 10))

            label.text = "00:00"
        }


   func currentPlayTime(timeString: String) { 
    dispatch_async(dispatch_get_main_queue()) { 
        self.label.text = timeString
    }
}

        func willPlay(status: Bool) {

        }
}

FirstViewController

class FirstViewController: BaseController {


    @IBAction func playButton(sender: AnyObject) {

        let urlString = "https://someStreamUrl"

        SharedPlayer.sharedInstance.setUrl(urlString)
        SharedPlayer.sharedInstance.play()

      }

}

SecondViewController

class SecondViewController : BaseController {

    override func viewDidLoad() {

        super.viewDidLoad()
        view.backgroundColor = .redColor()
    } 
}

1 个答案:

答案 0 :(得分:4)

主要缺陷是SharedPlayer是单身人士。只有一个例子。它只能有一个代表。但是你创建了两个视图控制器。两者都试图告诉单个共享SharedPlayer实例它是委托。第二个获胜。

委托模式仅在有一个委托时才有效。在这种情况下,您有两个,因此您无法使用传统的委托模式。

有一些可能的解决方案。

  1. 更新SharedPlayer以接受一组代表而不是一个代表。
  2. 使用NSNotificationCenter。发布SharedPlayer个帖子通知,让每个视图控制器注册每个可能的通知。