質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

1回答

946閲覧

前画面から垂れ流しているBGMを画面遷移と同時に停止させたい

mokoporon

総合スコア26

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2017/10/02 08:42

しっかりとまとめられず、質問が長文となっている事、ご容赦ください。

現在、単純な二択クイズアプリを制作しています。複数のページをセグエで接続しており、「タイトル画面」・「クイズ画面」・間違いを選んだ場合の「残念、タイトルに戻る画面」から構成されています。

「タイトル画面のBGM」と「ゲーム中BGM」が用意されており、問題に間違えるまでは「ゲーム中BGM」を垂れ流しにしたいと考えています。
間違えた時点で「ブブー」というSEとともにhoge.stop()でBGMを止め、タイトル画面に戻った際のBGM重複を防いでいます。

しかし、この方法では後述の問題が発生します。

タイトル画面(ViewContoroller)では、ViewDidLoad内に

Swift

1//BGMに関する部分以外は省略。 2import UIKit 3import AVFoundation 4 5var player:AVAudioPlayer? 6 7override func viewDidLoad() { 8 super.viewDidLoad() 9 10 let url = Bundle.main.bundleURL.appendingPathComponent("titlemus.mp3") 11 do { 12 try player = AVAudioPlayer(contentsOf: url) 13 } catch { 14 print("Error") 15 } 16 player!.play() 17 player!.numberOfLoops = -1 18 }

と書いてあり、アプリ起動と同時にBGMが再生されます(ちなみに、オプショナルの知識もまだまだしっかりとは理解しておらず、player!.play() でも player?.play()でも再生されたので、とりあえず ! で記載をしています)。

タイトル画面のGame Startを押すと、画面遷移とともにBGMが切り替わります。(FirstViewControllerへ遷移)

Swift

1import UIKit 2import AVFoundation 3 4class FristViewController: UIViewController { 5 6 //ゲーム中BGM 7 var player2:AVAudioPlayer? 8 //正解の場合のSE 9 var ongaku1:AVAudioPlayer? 10 //間違いの場合のSE 11 var music1:AVAudioPlayer? 12 13 @IBOutlet weak var label: UILabel! 14 15 override func viewDidLoad() { 16 super.viewDidLoad() 17 18 //画面遷移をした際に切り替わるBGMを設定。(ゲーム中のBGM) 19 20 let url = Bundle.main.bundleURL.appendingPathComponent("gameplay.mp3") 21 do { 22 try player2 = AVAudioPlayer(contentsOf: url) 23 } catch { 24 print("Error") 25 } 26 player2!.play() 27 player2!.numberOfLoops = -1 28 player2!.volume = 0.6 29 30 self.label.text = "問題文1" 31 } 32 33 override func didReceiveMemoryWarning() { 34 super.didReceiveMemoryWarning() 35 // Dispose of any resources that can be recreated. 36 } 37 38 /*seikai1ボタンはセグエで接続されており、タップすると次の問題画面に切り替わる。 39 その際に「ピンポン(seikai.mp3)」という音が鳴る。*/ 40 @IBAction func seikai1(_ sender: Any) { 41 let t1 = Bundle.main.bundleURL.appendingPathComponent("seikai.mp3") 42 do { 43 try ongaku1 = AVAudioPlayer(contentsOf: t1) 44 } catch { 45 print("Error") 46 } 47 ongaku1!.play() 48 49 } 50 51 /*machigai1ボタンはセグエで接続されており、タップすると残念画面に切り替わる。 52 その際に「ブブー(machigai.mp3)」という音が鳴る。*/ 53 @IBAction func machigai1(_ sender: Any) { 54 let f1 = Bundle.main.bundleURL.appendingPathComponent("machigai.mp3") 55 do { 56 try music1 = AVAudioPlayer(contentsOf: f1) 57 } catch { 58 print("Error") 59 } 60 music1!.play() 61 62 //ここでplayer2(ゲーム中BGM)を止めることで、音楽の重複を防いでいる。 63 player2!.stop() 64 } 65 66}

という具合にしています。この方法ですと、前述のとおり第一問(FirstViewController)で間違えた際には、ゲーム中BGM、タイトルBGMが被らずにタイトルに戻ることができます。しかし、ここで正解を選んだ場合、SecondViewController画面へと遷移をします。問題なのはここからで、二問目以降で間違えた場合、ゲーム中BGMとタイトルBGMが重複してしまいます。

Swift

1import UIKit 2import AVFoundation 3 4class SecondViewController: UIViewController { 5 6 var ongaku2 : AVAudioPlayer? 7 var music2 : AVAudioPlayer? 8 9//省略 10 11 @IBAction func seikai2(_ sender: Any) { 12 let t2 = Bundle.main.bundleURL.appendingPathComponent("seikai.mp3") 13 do { 14 try ongaku2 = AVAudioPlayer(contentsOf : t2) 15 } catch { 16 print("Error") 17 } 18 ongaku2!.play() 19 } 20 21 @IBAction func machigai2(_ sender: Any) { 22 let f2 = Bundle.main.bundleURL.appendingPathComponent("machigai.mp3") 23 do { 24 try music2 = AVAudioPlayer(contentsOf : f2) 25 } catch { 26 print("Error") 27 } 28 music2!.play() 29 30 //理想としては、ここでBGMを止めたいが...(他画面では前画面のコードは引き継がれずエラー) 31 player2!.stop() 32 } 33 34}

SecondViewController でも新たにBGMを設定すれば、間違いと同時にBGMを止めることはできますが、前画面から垂れ流しているBGMを止める方法がわかりません。(以降、Third・Fourth画面等も同様)
どのようにすれば、前画面から垂れ流しているBGMを止めることができるでしょうか。ご教授をよろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fuzzball

2017/10/03 00:44

ナビゲーションコントローラを使っていますか?
mokoporon

2017/10/04 06:30

恥ずかしながら、初心者でイマイチ使い方が分からなかったため、使用していません。
guest

回答1

0

ベストアンサー

曲を管理するシングルトンなクラスを作って下さい。
シングルトンが分からなければAppDelegateでもいいと思います。(とりあえずは)

投稿2017/10/03 00:44

fuzzball

総合スコア16731

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mokoporon

2017/10/04 06:29

ご回答ありがとうございます。お返事が遅れてしまい申し訳ありません。 AppDelegateについてなのですが、質問をした直後、私なりに少々調べ http://trade-and-develop.hatenablog.com/entry/2015/12/06/221851 こちらを参照すれば自己解決できるのではないかと思い、古いバージョンと注意されそうなところは自分なりに変更しつつ、実際にコードを写させていただきました。以下の二点を変更し、あとは上記参考サイト様のとおり書いています。 [変更前]NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("bgm", ofType: "mp3")!) [変更後]Bundle.main.bundleURL.appendingPathComponent("bgm.mp3") [変更前]audioPlayer = try? AVAudioPlayer(contentsOfURL:sound_data) [変更後]audioPlayer = try? AVAudioPlayer(contentsOf:sound_data) すると、class AppDelegate: UIResponder, UIApplicationDelegate の行で 「Invalid redeclaration of 'AppDelegate'」というエラーが出てきます。意味を調べると、「AppDelegateは無効な再宣言」ということで、なぜこのエラーが出るのか分からずに困っています。 https://samekard.blogspot.jp/2014/09/swifterror.html 上記のサイトによれば、「新しいクラスや構造体を定義しようとしたが、そのクラス名はすでにある場合」に出るらしいのですが、そのようなクラス名を使用した覚えはなく…。 もう少し、初心者に付き合っていただけると助かります。
fuzzball

2017/10/04 06:33

AppDelegateは新規に作成するのではなく、元々あるAppDelegate.swiftを使って下さい。
mokoporon

2017/10/04 07:30

お早いご回答ありがとうございます! しっかりと見ておらず、恥ずかしいことを書いてしまっていたようですね…。 AppDelegate.swiftにて上記参考サイト様のコードを書き、止めたいクラスに記すことでBGMを重複させることなく止めることができました。ありがとうございました! また機会があればよろしくお願いいたします!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問