我正在构建一个包含多个 View Controller 的应用程序。我需要控制所有音乐,所以我创建了一个专门的音乐类,用于设置/播放/停止/暂停。
我已经录制了音频问题和答案,我需要能够播放问题,然后是答案 mp3 文件。
所以我相信这里有一些方法可以完成这个委托(delegate)和协议(protocol),使用 func audioPlayerDidFinishPlaying 和使用闭包。据我所知,闭包是我想要实现的目标的最佳选择。
我在 MakeMusic 类(class)中的起点是:
class MakeMusicClass : NSObject, AVAudioPlayerDelegate {
static let shared = MakeMusicClass()
var audioPlayer = AVAudioPlayer()
override init() { }
func setup(Selection: String) {
do {
audioPlayer = try AVAudioPlayer(contentsOf: URL.init(fileURLWithPath: Bundle.main.path(forResource: Selection, ofType: "mp3")!))
audioPlayer.prepareToPlay()
audioPlayer.delegate=self
} catch {
print (error)
}
}
func play() {
audioPlayer.play()
}
我的调用文件是:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
MakeMusicClass.shared.setup(Selection: "Question11")
MakeMusicClass.shared.play()
MakeMusicClass.shared.setup(Selection: "Answer11")
MakeMusicClass.shared.play()
为了让它工作,我知道我需要向被调用的类添加一个闭包:
func play() {
var closure = { in
audioPlayer.play()
}
}
我需要更新我需要调用函数的地方,例如:
override func viewDidLoad() {
super.viewDidLoad()
MakeMusicClass.shared.setup(Selection: "Question11")
MakeMusicClass.shared.play() {
MakeMusicClass.shared.setup(Selection: "Answer11")
MakeMusicClass.shared.play()
}
我花了很长时间试图解决这个问题,但我很挣扎。我这里的代码显然不起作用,因为我缺少一些基本的东西。我试过传递void和参数,但我不明白应该传递什么参数。我最接近的是在 makemusic 类中使用 audioPlayerDidFinishPlaying 触发下一个音频文件,但我不知道这是否理想。
最佳答案
我认为您最好的选择是在您的 MakeMusicClass 中使用 Array 作为初始化程序,例如一个问题和答案,然后使用 AVAudioPlayerDelegate 触发下一个文件,我认为这就是您想要达到的目标(并且非常接近 ^________*)。
例如:
class AudioLooper: NSObject, AVAudioPlayerDelegate {
var debugView = true
var audioLoopPlayer: AVAudioPlayer!
var audioFileIndex: Int = 0
var audioFileArray: [String] = []
//-------------------------------------------------
//MARK: Audio Player Initialisation & Functionality
//-------------------------------------------------
/// Function To Initialise The Audio Loop Player
///
/// - Parameter audioFiles: [String] - The Array Of Audio Files To Play
func initAudioPlayerWith(audioFiles: [String]) {
audioFileArray = audioFiles
if debugView { print("Audio Files To Play In Sequence == \(audioFileArray)") }
}
/// Function To Play An Array Of Audio Files
///
/// - Parameter index: (Int) - The Current Index Of The Audio Sequence
func playAudioLoopAt(index: Int) {
let currentAudioFile = "\(audioFileArray[audioFileIndex])"
if let audioFilePath = Bundle.main.path(forResource: currentAudioFile, ofType: "mp3"){
do {
let audioFileUrl = NSURL.fileURL(withPath: audioFilePath)
// Set An Instance Of AVAudioSession Which Allows Playback Even When Device Is Muted
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
try AVAudioSession.sharedInstance().setActive(true)
audioLoopPlayer = try AVAudioPlayer(contentsOf: audioFileUrl)
audioLoopPlayer.prepareToPlay()
audioLoopPlayer.delegate = self
audioLoopPlayer.play()
if debugView { print("Playing \(currentAudioFile) ") }
audioFileIndex += 1
} catch {
print("Error Playing Audio")
}
} else {
print("Error Finding File: \(currentAudioFile)")
}
}
/// Function To Continue The Audio Sequence
@objc func continueAudioLoop(){
playAudioLoopAt(index: audioFileIndex)
}
/// Function To Stop The Audio Looop Player
func stopAudioPlayer() {
if audioLoopPlayer != nil {
audioFileIndex=0
audioLoopPlayer.stop()
audioLoopPlayer = nil
}
}
//-----------------------------
//MARK: AVAudio Player Delegate
//-----------------------------
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
if audioFileIndex < audioFileArray.count {
self.perform(#selector(continueAudioLoop), with: self, afterDelay: 0.5)
}else{
audioFileIndex=0
}
}
}
在我的示例中,您只需像这样初始化:
audioLooper = AudioLooper()
audioLooper?.initAudioPlayerWith(audioFiles: ["question", "answer"])
audioLooper?.playAudioLoopAt(index: 0)
像这样声明 audioLooper 的地方:var audioLooper:AudioLooper?
显然我的示例不是单例,但它应该让您了解如何调整 MakeMusicClass 以使其适合...
您还可以像这样添加一个Delegate 方法来通知ViewController 音频已完成或执行一些其他任务,例如更新下一个问题等,例如:
@objc protocol AudioLooperDelegate {
@objc optional func update()
}
然后在您的 ViewController 中:
var delegate: AudioLooperDelegate?
然后在 AudioLooper 类中,您可以在需要的地方添加委托(delegate)方法,例如:
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
if audioFileIndex < audioFileArray.count {
self.perform(#selector(continueAudioLoop), with: self, afterDelay: 0.5)
}else{
audioFileIndex=0
delegate?.updateUI!()
}
}
}
关于ios - Swift 需要关闭音频播放器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49081121/
当我使用Bundler时,是否需要在我的Gemfile中将其列为依赖项?毕竟,我的代码中有些地方需要它。例如,当我进行Bundler设置时:require"bundler/setup" 最佳答案 没有。您可以尝试,但首先您必须用鞋带将自己抬离地面。 关于ruby-我需要将Bundler本身添加到Gemfile中吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/4758609/
我注意到像bundler这样的项目在每个specfile中执行requirespec_helper我还注意到rspec使用选项--require,它允许您在引导rspec时要求一个文件。您还可以将其添加到.rspec文件中,因此只要您运行不带参数的rspec就会添加它。使用上述方法有什么缺点可以解释为什么像bundler这样的项目选择在每个规范文件中都需要spec_helper吗? 最佳答案 我不在Bundler上工作,所以我不能直接谈论他们的做法。并非所有项目都checkin.rspec文件。原因是这个文件,通常按照当前的惯例,只
我实际上是在尝试使用RVM在我的OSX10.7.5上更新ruby,并在输入以下命令后:rvminstallruby我得到了以下回复:Searchingforbinaryrubies,thismighttakesometime.Checkingrequirementsforosx.Installingrequirementsforosx.Updatingsystem.......Errorrunning'requirements_osx_brew_update_systemruby-2.0.0-p247',pleaseread/Users/username/.rvm/log/138121
这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下
我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的
下面的代码在我第一次运行它时就可以正常工作:require'rubygems'require'spreadsheet'book=Spreadsheet.open'/Users/me/myruby/Mywks.xls'sheet=book.worksheet0row=sheet.row(1)putsrow[1]book.write'/Users/me/myruby/Mywks.xls'当我再次运行它时,我会收到更多消息,例如:/Library/Ruby/Gems/1.8/gems/spreadsheet-0.6.5.9/lib/spreadsheet/excel/reader.rb:11
这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Rubysyntaxquestion:Rational(a,b)andRational.new!(a,b)我正在阅读ruby镐书,我对创建有理数的语法感到困惑。Rational(3,4)*Rational(1,2)产生=>3/8为什么Rational不需要new方法(我还注意到例如我可以在没有new方法的情况下创建字符串)?
1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里
我需要用任何语言编写一个算法,根据3个因素对数组进行排序。我以度假村为例(如Hipmunk)。假设我想去度假。我想要最便宜的地方、最好的评论和最多的景点。但是,显然我找不到在所有3个中都排名第一的方法。Example(assumingthereare20importantattractions):ResortA:$150/night...98/100infavorablereviews...18of20attractionsResortB:$99/night...85/100infavorablereviews...12of20attractionsResortC:$120/night
一段时间以来,我一直在使用open_uri下拉ftp路径作为数据源,但突然发现我几乎连续不断地收到“530抱歉,允许的最大客户端数(95)已经连接。”我不确定我的代码是否有问题,或者是否是其他人在访问服务器,不幸的是,我无法真正确定谁有问题。本质上,我正在读取FTPURI:defself.read_uri(uri)beginuri=open(uri).readuri=="Error"?nil:urirescueOpenURI::HTTPErrornilendend我猜我需要在这里添加一些额外的错误处理代码...我想确保我采取一切预防措施来关闭所有连接,这样我的连接就不是问题所在,但是我