从另一个ViewController在swift中调用函数

我已经看了Stackoverflow,但我无法得到答案。 我想要创build停止在另一个ViewController中播放声音的函数。 但是,当我点击停止button时,它破解并显示“EXC_BAD_INSTRUCTION(code = EXC_I386_INVOP,subcode = 0x0)”。 这是我的代码。

第一个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) } } 

另一个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)" } } 

如果你想从one_view_controller按下button,并停止在另一个视图控制器上的声音,然后按照此。

遵循以下步骤:

步骤1 :

添加这个代码在你的视图控制器,你想按下button单击停止声音。

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

第2步:

现在是最后一步。 现在将下面的代码添加到您的结果视图控制器,您想要自动停止声音。

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

现在在编码中实现这个代码。 希望对你有效。

您正在创build一个FirstVC的新副本,并在尚未初始化的东西上调用stop。

在这种情况下,你应该真的使用委托,就像

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

所以你将第一个VC传给第二个VC,所以当你调用这些函数的时候,你正在使用实际的FirstVC,而不是创build一个新的VC。

你可以做这个没有协议,如果你喜欢通过replacevar delegate: controlsAudio?var firstVC: FirstVC? 并分配,但我不会推荐它

您正在使用FirstVC viewDidLoad方法初始化metronome 。 在SecondVC ,您将初始化metronomePlay作为存储属性,但从不要求ViewController的视图,因此FirstVC viewDidLoad不会被调用,从而导致metronome (存储属性)未初始化。

 var metronomePlay = FirstVC() 

您正在FirstVC上创build一个新的实例,而应该在已经加载的FirstVC的同一个实例上执行该函数。

你在初始化FirstVC中的第一个FirstVC viewDidLoad ,这将不会发生,直到加载在SecondVC实例化的metronomePlay播放的视图。 在实际调用metronomePlay.metronome之前,您必须首先在SecondVC上调用_ = metronomePlay.view metronomePlay.metronome

更新@Scriptable的Swift 4的答案

步骤1 :

添加这个代码在你的视图控制器,你想按下button单击停止声音。

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

第2步:

现在是最后一步。 现在将下面的代码添加到您想要自动停止声音的结果视图控制器中。

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

在SecondVC中试试这个。 var metronomePlay = FirstVC()。节拍器