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

And*_*opf 16 ios avplayer swift

我已经查看了Stackoverflow但我无法得到答案.我想创建停止在另一个ViewController中播放声音的函数.但是当我点击停止按钮时,它会破解并显示"EXC_BAD_INSTRUCTION(代码= EXC_I386_INVOP,子代码= 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)
    }
}
Run Code Online (Sandbox Code Playgroud)

另一个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)"
   }
}
Run Code Online (Sandbox Code Playgroud)

小智 19

斯威夫特 5:

把这个放在行动中

NotificationCenter.default.post(name: Notification.Name("NewFunctionName"), object: nil)
Run Code Online (Sandbox Code Playgroud)

把它放在不同的视图控制器中的 viewdidload() 中(你要使用的函数在哪里)

NotificationCenter.default.addObserver(self, selector: #selector(functionName), name: Notification.Name("NewFunctionName"), object: nil)
Run Code Online (Sandbox Code Playgroud)

功能

 @objc func functionName (notification: NSNotification){ //add stuff here}
Run Code Online (Sandbox Code Playgroud)

我希望我有帮助


Scr*_*ble 14

您正在创建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)

}
Run Code Online (Sandbox Code Playgroud)

因此,您将第一个VC传递给第二个VC,因此当您调用这些函数时,您正在使用的实际FirstVC上执行此操作,而不是创建新的.

如果您通过更换喜欢,你可以做到这一点没有协议,var delegate: controlsAudio?var firstVC: FirstVC?和分配,但我不会推荐它


sha*_*zar 13

从今天的swift 4.1开始,这段代码对我有用:

把它放在发送控制器:

NotificationCenter.default.post(name: Notification.Name(rawValue: "disconnectPaxiSockets"), object: nil)
Run Code Online (Sandbox Code Playgroud)

把它放在接收控制器viewDidLoad()或viewWillAppear()中:

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

然后接收控制器类中的以下函数:

@objc func disconnectPaxiSocket(_ notification: Notification) {
    ridesTimer.invalidate()
    shared.disconnectSockets(socket: self.socket)
}
Run Code Online (Sandbox Code Playgroud)


小智 5

我使用这种方式从另一个viewControllers调用我的函数:

let sendValue = SecondViewController();
sendValue.YourFuncion(data: yourdata);
Run Code Online (Sandbox Code Playgroud)


Amy*_*yth 5

您可以通过多种方式从其他 viewController 调用函数。

上面已经讨论过的两种方式是通过代表和协议以及通过发送通知。

另一种方法是将闭包从firstVC 传递到第二个viewController。

下面是在继续执行 SecondVC 时我们传递一个闭包来停止节拍器的代码。不会有任何问题,因为您传递的是相同的firstVC(而不是创建新实例),因此节拍器不会为零。

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

      let secondVC = SecondVC()
      secondVC.stopMetronome = { [weak self] in
        self?.metronome.stop()
      }
      present(secondVC, animated: true)

    }
}


class SecondVC: UIViewController {
   var metronomePlay = FirstVC()
   var stopMetronome: (() -> Void)? // stopMetronome closure

   @IBAction func stopBtnPressed(_ sender: Any) {
      if let stopMetronome = stopMetronome {
         stopMetronome() // calling the closure
      }

   }

 }
Run Code Online (Sandbox Code Playgroud)


Pun*_*rma 0

您正在使用 的方法metronome进行初始化。在 中,您将初始化为存储属性,但从不请求 ViewController 的视图,因此of不会被调用,从而导致(存储属性)未初始化。viewDidLoadFirstVCSecondVCmetronomePlayviewDidLoadFirstVCmetronome