我很难理解为什么我的代理在基本控制器中定义的不在继承的视图控制器中工作。
我有一个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()
}
}
答案 0 :(得分:4)
主要缺陷是SharedPlayer
是单身人士。只有一个例子。它只能有一个代表。但是你创建了两个视图控制器。两者都试图告诉单个共享SharedPlayer
实例它是委托。第二个获胜。
委托模式仅在有一个委托时才有效。在这种情况下,您有两个,因此您无法使用传统的委托模式。
有一些可能的解决方案。
SharedPlayer
以接受一组代表而不是一个代表。NSNotificationCenter
。发布SharedPlayer
个帖子通知,让每个视图控制器注册每个可能的通知。