如何从独立类中获取通知(Swift 3)

时间:2017-03-31 06:42:49

标签: ios swift swift3 nsnotificationcenter

一旦观察者在另一个中获得通知,我想在类中调用方法。问题是我不能从另一个类调用一个类,因为我将接受递归调用。

1)带有Player实例的控制器类:

//  PlayerController.swift
//  player

import UIKit
import MediaPlayer

class NowPlayingController: NSObject {

    var musicPlayer: MPMusicPlayerController {
        if musicPlayer_Lazy == nil {
            musicPlayer_Lazy = MPMusicPlayerController.systemMusicPlayer()
            let center = NotificationCenter.default
            center.addObserver(
                self,
                selector: #selector(self.playingItemDidChange),
                name: NSNotification.Name.MPMusicPlayerControllerNowPlayingItemDidChange,
                object: musicPlayer_Lazy)
            musicPlayer_Lazy!.beginGeneratingPlaybackNotifications()
        }

        return musicPlayer_Lazy!
    }

    //If song changes
    func playingItemDidChange(notification: NSNotification) {
        //somehow call updateSongInfo() method from 2nd class
    }

    //Get song metadata
    func getSongData() -> (UIImage, String?, String?) {
        let nowPlaying = musicPlayer.nowPlayingItem

        //...some code
        return (albumImage, songName, artistAlbum)
    }

    func updateProgressBar() -> (Int?, Float?){
        let nowPlaying = musicPlayer.nowPlayingItem
        var songDuration: Int?
        var elapsedTime: Float?

        songDuration = nowPlaying?.value(forProperty: MPMediaItemPropertyPlaybackDuration) as? Int
        elapsedTime = Float(musicPlayer.currentPlaybackTime)

        return(songDuration, elapsedTime)
    }
}

2)查看控制器,当玩家控制器获得通知时应该更新

//  MainViewController.swift
//  player

import UIKit

class MainViewController: UIViewController {

    let playerController = PlayerController()
    @IBOutlet weak var albumView: UIImageView!
    @IBOutlet weak var songLabel: UILabel!
    @IBOutlet weak var artistAlbum: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()

        //Start updating progress bar
        Timer.scheduledTimer(timeInterval: 0.5,
                         target: self,
                         selector: #selector(MainViewController.updateProgressBar),
                         userInfo: nil,
                         repeats: true)
    }

    private func updateSongInfo(){
        (albumView.image!, songLabel.text, artistAlbum.text) = playerController.getSongData()
    }

    private func updateProgressBar(){
        (progressBar.maximumValue, progressBar.value) = playerController.playingItemProgress()
}
}

Swift 3的解决方案:

在NowPlayingController中:

let newSongNotifications = NSNotification(name:NSNotification.Name(rawValue: "updateSongNotification"), object: nil, userInfo: nil)

func playingItemDidChange(notification: NSNotification) {
        NotificationCenter.default.post(newSongNotifications as Notification)
}

在其他控制器中:

override func viewDidLoad() {
    super.viewDidLoad()

    NotificationCenter.default.addObserver(self, selector: #selector(self.updateSongInfo), name: NSNotification.Name(rawValue: "updateSongNotification"), object: nil)
}

2 个答案:

答案 0 :(得分:1)

您可以在您需要的自定义对象中发布通知:

    let notification = NSNotification(name:"doSomethingNotification", object: nil, userInfo: nil)
    NotificationCenter.defaultCenter.postNotification(notification)

然后在您想要执行某些操作以响应此通知的其他视图控制器中,您告诉它在viewDidLoad()中观察通知。您传入的选择器是您在收到通知时要执行的方法。

    override func viewDidLoad(){
        super.viewDidLoad()

        NotificationCenter.addObserver(self, selector: #selector(self.doSomething), name: "doSomethingNotification", object: nil)
    }

答案 1 :(得分:0)

您可以使用委托方法更新MainViewController