我试图在swift / xcode中利用AVSpeechSynthesizer读取一些文本。我大部分时间都在工作。我对其进行了设置,以便如果它们返回上一个屏幕或下一个屏幕,则音频将停止。但在我的情况下,如果希望以其他方式提出另一种观点,我希望演讲继续进行。例如,我有一个退出按钮,单击该按钮会显示一个“确定要退出吗?是/否”类型的屏幕,但是我希望音频继续播放,直到它们单击“是”并被带走。我也有另一种可以模态表示的观点,希望在这种情况下继续播放音频。
有人知道如何以一种方式在上方显示视图时保持语音播放,但在完全导航到另一个视图时如何停止播放?
到目前为止,这是我的代码:
//Press Play/Pause Button
@IBAction func playPauseButtonAction(_ sender: Any) {
if(isPlaying){
//pause
synthesizer.pauseSpeaking(at: AVSpeechBoundary.immediate)
playPauseButton.setTitle("Play", for: .normal)
} else {
if(synthesizer.isPaused){
//resume playing
synthesizer.continueSpeaking()
} else {
//start playing
theUtterance = AVSpeechUtterance(string: audioTextLabel.text!)
theUtterance.voice = AVSpeechSynthesisVoice(language: "en-UK")
synthesizer.speak(theUtterance)
}
playPauseButton.setTitle("Pause", for: .normal)
}
isPlaying = !isPlaying
}
//Press Stop Button
@IBAction func stopButtonAction(_ sender: Any) {
if(isPlaying){
//stop
synthesizer.stopSpeaking(at: AVSpeechBoundary.immediate)
playPauseButton.setTitle("Play", for: .normal)
isPlaying = !isPlaying
}
}
//Leave Page
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
synthesizer.stopSpeaking(at: .immediate)
}
答案 0 :(得分:1)
问题出在您的viewWillDisappear
上。任何一种新的屏幕都会触发此操作,因此实际上将调用您的代码synthesizer.stopSpeaking(at: .immediate)
,从而停止音频。其中包括演示或推送新控制器。
现在,如何改善它?您已经提到了这一点:
我对其进行了设置,以便它们返回上一个屏幕或 在下一屏幕上,音频将停止
首先,如果他们返回上一个屏幕:
您想在您的内部执行相同的音频代码行停止
deinit { }
方法。这将使您知道屏幕或控制器已从内存中删除,这意味着控制器已在控制器堆栈中移走(用户返回到上一屏幕)。只要您没有保留周期计数问题,此方法就可以100%正常工作。
接下来,到下一个屏幕,您可以轻松地在停止推送新屏幕的功能中包含相同的代码行。
答案 1 :(得分:0)
经过大量研究,我能够获得所需的功能。正如Glenn所建议的那样,正确的方法是在deinit
中而不是viewWillDisappear
中调用stopSpeaking。问题是通常使用AVSpeechSynthesizer
/ AVSpeechSynthesizerDelegate
会创建对ViewController的强引用,因此不会调用deinit。为了解决这个问题,我必须创建一个自AVSpeechSynthesizerDelegate
继承的自定义类,但使用对自定义协议的弱委托引用。
自定义类和协议:
import UIKit
import AVFoundation
protocol AudioTextReaderDelegate: AnyObject {
func speechDidFinish()
}
class AudioTextReader: NSObject, AVSpeechSynthesizerDelegate {
let synthesizer = AVSpeechSynthesizer()
weak var delegate: AudioTextReaderDelegate!
//^IMPORTANT to use weak so that strong reference isn't created.
override init(){
super.init()
self.synthesizer.delegate = self
}
func startSpeaking(_ toRead: String){
let utterance = AVSpeechUtterance(string: toRead)
synthesizer.speak(utterance)
}
func resumeSpeaking(){
synthesizer.continueSpeaking()
}
func pauseSpeaking(){
synthesizer.pauseSpeaking(at: .immediate)
}
func stopSpeaking() {
synthesizer.stopSpeaking(at: .immediate)
}
func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didFinish utterance: AVSpeechUtterance) {
self.delegate.speechDidFinish()
}
}
然后在我的ViewController中继承并使用它:
import UIKit
import AVFoundation
class MyClassViewController: UIViewController, AudioTextReaderDelegate{
var isPlaying = false
let audioReader = AudioTextReader()
let toReadText = "This is the text to speak"
@IBOutlet weak var playPauseButton: UIButton!
@IBOutlet weak var stopButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
self.audioReader.delegate = self
}
//Press Play/Pause Button
@IBAction func playPauseButtonAction(_ sender: Any) {
if(isPlaying){
//Pause
audioReader.synthesizer.pauseSpeaking(at: .immediate)
playPauseButton.setTitle("Play", for: .normal)
} else {
if(audioReader.synthesizer.isPaused){
//Resume Playing
audioReader.resumeSpeaking()
} else {
audioReader.startSpeaking(toReadText)
}
playPauseButton.setTitle("Pause", for: .normal)
}
isPlaying = !isPlaying
}
//Press Stop Button
@IBAction func stopButtonAction(_ sender: Any) {
if(isPlaying){
//Change Button Text
playPauseButton.setTitle("Play", for: .normal)
isPlaying = !isPlaying
}
//Stop
audioReader.stopSpeaking()
}
//Finished Reading
func speechDidFinish() {
playPauseButton.setTitle("Play", for: .normal)
isPlaying = !isPlaying
}
//Leave Page
deinit {
audioReader.stopSpeaking()
playPauseButton.setTitle("Play", for: .normal)
isPlaying = !isPlaying
}
@IBAction func NextStopButton(_ sender: Any) {
audioReader.stopSpeaking()
playPauseButton.setTitle("Play", for: .normal)
isPlaying = !isPlaying
}
}
我希望这对以后的人有所帮助,因为这使我无所适从。