Вызов функции из другого класса (Паттерн Наблюдатель) Swift 5

August 13, 2019

Одна из частых задач при написании приложения на Swift - передача данных из одного VC в другой. На этот раз мне нужно было вызвать функцию и остановить воспроизведение аудиопотока из нового VC.

Имеется два контроллера:

В ViewController есть функция pausePlayback(), останавливающая воспроизведение аудио.

class ViewController: UIViewController {

    //CODE

    

    override func viewDidLoad() {

        super.viewDidLoad()

        //CODE

    }

    

    //Pause the playback

    @objc func pausePlayback() {

        radioPlayer.pause()

    }

}

В TimerViewController есть кнопка, при нажатии которой через 2.0 секунды выполняется функция timerButton. 

class TimerViewController: UIViewController {

    

    @IBAction func timerButton(_ sender: Any) {

        DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {

            // Delayed code

            print("This worked")

        }

    }

    

    override func viewDidLoad() {

        super.viewDidLoad()

    }

}

Задача: вызвать функцию pausePlayback() из первого View Controller:

Есть три основных способа, описанные в этой статье на Medium. Я выбрал первый, с примером из этой статьи. Этот паттерн называется "Наблюдатель". Больше информации на русском здесь.

В первый VC добавляем переменную ncObserver, а в viewDidLoad() добавляем функцию наблюдателя: 

class ViewController: UIViewController {

  

    let ncObserver = NotificationCenter.default  

    

    override func viewDidLoad() {

        super.viewDidLoad()

        

        ncObserver.addObserver(self, selector: #selector(self.pausePlayback), name: Notification.Name("PauseMusic"), object: nil)

    }

    

    //Pause the playback

    @objc func pausePlayback() {

        radioPlayer.pause()

    }

}

В TimerViewController добавляем переменную notification для оповещений, а в функцию, вызываемую кнопкой, добавляем результат оповещения self.notification.post.

class TimerViewController: UIViewController {

    

    let notification = NotificationCenter.default

    @IBAction func timerButton(_ sender: Any) {

        DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) { // Change `2.0` to the desired number of seconds.

            // Code you want to be delayed

            print("This worked")

            self.notification.post(name: Notification.Name("PauseMusic"), object: nil)

        }

    }

    

    override func viewDidLoad() {

        super.viewDidLoad()

    }

}

Готово! Теперь функция из одного VC вызывается в другом!