Call function from another ViewController in fast mode

I already looked in Stackoverflow, but I can not get the answer. I want to create a function that stops playing sound in another ViewController. But when I pressed the stop button, it hacked and showed "EXC_BAD_INSTRUCTION (code = EXC_I386_INVOP, subcode = 0x0)." This is my code.

First viewcontroller

import UIKit import AVFoundation class FirstVC: UIViewController { var metronome: AVAudioPlayer! override func viewDidLoad() { super.viewDidLoad() do { let resourcePath1 = Bundle.main.path(forResource: "music", ofType: "mp3") let url = NSURL(fileURLWithPath: resourcePath1!) try metronome = AVAudioPlayer(contentsOf: url as URL) metronome.prepareToPlay() metronome.play() } catch let err as NSError { print(err.debugDescription) } } 

and another Viewcontroller -

 import UIKit class SecondVC: UIViewController { var metronomePlay = FirstVC() @IBAction func stopBtnPressed(_ sender: Any) { metronomePlay.metronome.stop() //"EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)" } } 
+13
source share
10 answers

You create a new copy of FirstVC and call a stop on something that has not yet been initialized.

In this case, you really should use a delegate, something like

 protocol controlsAudio { func startAudio() func stopAudio() } class FirstVC: UIViewController, controlsAudio { func startAudio() {} func stopAudio() {} // later in the code when you present SecondVC func displaySecondVC() { let vc = SecondVC() vc.delegate = self self.present(vc, animated: true) } } class SecondVC: UIViewController { var delegate: controlsAudio? // to start audio call self.delegate?.startAudio) // to stop audio call self.delegate?.stopAudio) } 

So, you pass the first VC to the second VC, so when you call these functions, you do this on the actual FirstVC that is used, and not on creating a new one.

You can do this without protocols if you want by replacing var delegate: controlsAudio? on var firstVC: FirstVC? and assigning it, but I would not recommend it

+11
source

If you want to press a button from one_view_controller and stop the sound on another view controller, follow these steps:

Follow these steps:

Step 1:

Add this code to your controller from which you want to press a button to stop the sound.

 @IBAction func btnStopSound(_ sender: AnyObject) { NSNotificationCenter.defaultCenter().postNotificationName("stopSoundNotification", object: nil) } 

Swift 4 Version:

 @IBAction func btnStopSound(_ sender: AnyObject) { NotificationCenter.default.post(name: Notification.Name(rawValue: "setTimerValue"), object: nil) } 

Step 2:

Now is his last step. Now add this code below to the results controller where you want to automatically stop the sound.

 func loadList(notification: NSNotification){ metronomePlay.metronome.stop() } override func viewWillAppear(animated: Bool) { NSNotificationCenter.defaultCenter().addObserver(self, selector: "loadList:",name:"stopSoundNotification", object: nil) } 

Swift 4 Version:

 func loadList(notification: Notification){ metronomePlay.metronome.stop() } override func viewWillAppear(animated: Bool) { NotificationCenter.default.addObserver(self, selector: Selector(("loadList:")), name: Notification.Name(rawValue: "stopSoundNotification"), object: nil) } 

Now implement this code in your own encoding. Hope this works for you.

+8
source

Starting with swift 4.1, today this code worked for me:

Put this in the sending controller:

 NotificationCenter.default.post(name: Notification.Name(rawValue: "disconnectPaxiSockets"), object: nil) 

Put this in the receiving controller viewDidLoad () or viewWillAppear ():

 NotificationCenter.default.addObserver(self, selector: #selector(disconnectPaxiSocket(_:)), name: Notification.Name(rawValue: "disconnectPaxiSockets"), object: nil) 

and then the following function in your controller receive class:

 @objc func disconnectPaxiSocket(_ notification: Notification) { ridesTimer.invalidate() shared.disconnectSockets(socket: self.socket) } 
+4
source

Update @Scriptable answer for Swift 4

Step 1:

Add this code to your controller from which you want to press a button to stop the sound.

 @IBAction func btnStopSound(_ sender: AnyObject) { notificationCenter.post(name: Notification.Name("stopSoundNotification"), object: nil) } 

Step 2:

Now is his last step. Now add this code below to the result view controller, where you want to automatically stop the sound.

 func functionName (notification: NSNotification) { metronomePlay.metronome.stop() } override func viewWillAppear(animated: Bool) { NSNotificationCenter.defaultCenter().addObserver(self, selector: "functionName",name:"stopSoundNotification", object: nil) } 
+2
source

You initialize metronome in the viewDidLoad method of FirstVC . In SecondVC you initialize metronomePlay as a stored property, but you never request a ViewController view and, therefore, viewDidLoad of FirstVC does not receive a call whose results in metronome (stored property) do not receive initialization.

0
source
 var metronomePlay = FirstVC() 

you create a new instance on FirstVC, instead you must execute the function on the same instance as the already loaded FirstVC.

0
source

You initialize metronome to FirstVC in viewDidLoad , which will not happen until the view metronomePlay instantiated in SecondVC .

You must call _ = metronomePlay.view , which will lazily load the SecondVC and subsequently execute viewDidLoad before actually calling metronomePlay.metronome .

0
source

Either use the notification process to stop from anywhere, or use the same FirstVC instance from the SecondVC class.

0
source

I use this method to call my functions from another viewControllers:

 let sendValue = SecondViewController(); sendValue.YourFuncion(data: yourdata); 
0
source

Try this on SecondVC. var metronomePlay = FirstVC (). metronome

-one
source

Source: https://habr.com/ru/post/1014837/


All Articles