dandepeched
dandepeched

Reputation: 454

How to get Notification from standalone class (Swift 3)

I want to call method in a class as soon as observer get Notification in another one. The problem is that I cannot call one class from another, because I will get recursion call then.

1) Controller class with Player instance:

//  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) View controller which should be updated when Player Controller get notification

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

Solution for Swift 3:

In NowPlayingController:

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

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

And in other controller:

override func viewDidLoad() {
    super.viewDidLoad()

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

Upvotes: 1

Views: 1346

Answers (2)

emiledecosterd
emiledecosterd

Reputation: 81

You can post a notification from within your custom object where you need it:

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

And then in your other view controller in which you want to execute something in response to this notification, you tell it to observe the notification in viewDidLoad(). The selector you pass in is the method you want to be executed when the notification is received.

    override func viewDidLoad(){
        super.viewDidLoad()

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

Upvotes: 1

Albi
Albi

Reputation: 1855

You can use delegate method to update MainViewController

Upvotes: 0

Related Questions