BaseController 委托在选项卡栏控制器内的所有继承视图控制器中不起作用
BaseController delegate not working in all inherited view controllers inside tab bar controller
我很难理解为什么我在基本控制器中定义的委托在继承的视图控制器中不起作用。
我有一个 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)
}
}
}
基础控制器
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) {
}
}
第一个ViewController
class FirstViewController: BaseController {
@IBAction func playButton(sender: AnyObject) {
let urlString = "https://someStreamUrl"
SharedPlayer.sharedInstance.setUrl(urlString)
SharedPlayer.sharedInstance.play()
}
}
第二ViewController
class SecondViewController : BaseController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .redColor()
}
}
主要缺陷是 SharedPlayer
是单例。只有一个例子。它只能有一个代表。但是你创建了两个视图控制器。两者都试图告诉单个共享 SharedPlayer
实例它是委托。第二个赢了。
委托模式只有在有一个委托的情况下才有效。在这种情况下,您有两个,因此您不能使用传统的委托模式。
有几个可能的解决方案。
- 更新
SharedPlayer
以接受一组代表而不是单个代表。
- 使用
NSNotificationCenter
。有 SharedPlayer
post 个通知并让每个视图控制器注册每个可能的通知。
我很难理解为什么我在基本控制器中定义的委托在继承的视图控制器中不起作用。
我有一个 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)
}
}
}
基础控制器
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) {
}
}
第一个ViewController
class FirstViewController: BaseController {
@IBAction func playButton(sender: AnyObject) {
let urlString = "https://someStreamUrl"
SharedPlayer.sharedInstance.setUrl(urlString)
SharedPlayer.sharedInstance.play()
}
}
第二ViewController
class SecondViewController : BaseController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .redColor()
}
}
主要缺陷是 SharedPlayer
是单例。只有一个例子。它只能有一个代表。但是你创建了两个视图控制器。两者都试图告诉单个共享 SharedPlayer
实例它是委托。第二个赢了。
委托模式只有在有一个委托的情况下才有效。在这种情况下,您有两个,因此您不能使用传统的委托模式。
有几个可能的解决方案。
- 更新
SharedPlayer
以接受一组代表而不是单个代表。 - 使用
NSNotificationCenter
。有SharedPlayer
post 个通知并让每个视图控制器注册每个可能的通知。