mp3データの音の再生にAVAudioPlayerを使用しているのですが、ページをめくって画面遷移していると途中でクラッシュしてしまいます。
具体的には、初期画面のテーブルビューのセルから画面遷移をし、遷移したページからページをいくらかめくったところでクラッシュしてしまいます。
audioPlayer関連のコードを消せば、ページめくりをしてもエラーは出ません。
mp3のデータを各ページ少なくするとエラーはでません。
約260コ分ぐらいののデータをページスクロールし続けたらクラッシュします。
テーブルビューにその都度戻って各ページに移動するにはエラーはでません。
上記のことから、mp3の音データはちゃんと揃ってあります。
エラーの原因や解決方法などを教えて頂けたら大変助かります。
宜しくお願い致します。
発生している問題・エラーメッセージ
該当コード内で audioPlayers.append(audioPlayer)のところで[Thread1: EXC BAD INSTRUCTION] デバックエリアの出力では Error The operation couldn\U2019t be completed. (NSOSStatusErrorDomain error -42.) fatal error: unexpectedly found nil while unwrapping an Optional value
該当のソースコード
[使用バージョン Swift3] import UIKit import AVFoundation class PageContentViewController: UIViewController, UIScrollViewDelegate, AVAudioPlayerDelegate { let soundNameArray = [ ["1","2","1","2","1","2","1","2","1","2","1","2","1","2","1","2"], // 1 ["1","2","1","2","1","2","1","2","1","2","1","2","1","2","1","2"], // 2 ["1","2","1","2","1","2","1","2","1","2","1","2","1","2","1","2"], // 3 ["1","2","1","2","1","2","1","2","1","2","1","2","1","2","1","2"], // 4 ["1","2","1","2","1","2","1","2","1","2","1","2","1","2","1","2"], // 5 ["1","2","1","2","1","2","1","2","1","2","1","2","1","2","1","2"], // 6 ["1","2","1","2","1","2","1","2","1","2","1","2","1","2","1","2"], // 7 ["1","2","1","2","1","2","1","2","1","2","1","2","1","2","1","2"], // 8 ["1","2","1","2","1","2","1","2","1","2","1","2","1","2","1","2"], // 9 ["1","2","1","2","1","2","1","2","1","2","1","2","1","2","1","2"], // 10 ["1","2","1","2","1","2","1","2","1","2","1","2","1","2","1","2"], // 11 ["1","2","1","2","1","2","1","2","1","2","1","2","1","2","1","2"], // 12 ["1","2","1","2","1","2","1","2","1","2","1","2","1","2","1","2"], // 13 ["1","2","1","2","1","2","1","2","1","2","1","2","1","2","1","2"], // 14 ["1","2","1","2","1","2","1","2","1","2","1","2","1","2","1","2"], // 15 ["1","2","1","2","1","2","1","2","1","2","1","2","1","2","1","2"], // 16 ["1","2","1","2","1","2","1","2","1","2","1","2","1","2","1","2"], // 17 ["1","2","1","2","1","2","1","2","1","2","1","2","1","2","1","2"], // 18 ["1","2","1","2","1","2","1","2","1","2","1","2","1","2","1","2"], // 19 ["1","2","1","2","1","2","1","2","1","2","1","2","1","2","1","2"] // 20 ] // 1つの配列に16コずつだと16ページ目でクラッシュ(17ページ目を呼ぶのにエラーがでている) var pageIndex:Int = 0 // 各ページのindex let indexPageLabel = UILabel() // index確認用ラベル // sound関係 var soundArray:[String] = [] // ファイル名のデータを格納する var audioUrls:[URL] = [] // soundArrayの要素からパスとurlを作成し格納する var audioPlayer:AVAudioPlayer! // urlから音声データにして格納する var audioPlayers:[AVAudioPlayer] = [] // 音声データを格納する var soundButtons = [UIButton]() // 音声を鳴らすボタンを格納する override func viewDidLoad() { super.viewDidLoad() // indexPageラベル indexPageLabel.frame = CGRect(x: 20, y: 10, width: 240, height: 20) indexPageLabel.text = "pageIndex: (pageIndex) ページNo: ((pageIndex) + 1)" indexPageLabel.backgroundColor = .yellow self.view.addSubview(indexPageLabel) soundArray = soundNameArray[pageIndex] // soundArrayの要素すべてを取り出してaudioPlayers配列に格納する for i in soundArray { let audioPath = Bundle.main.path(forResource: "(i)", ofType:"mp3")! let audioUrl = URL(fileURLWithPath: audioPath) do { audioPlayer = try AVAudioPlayer(contentsOf: audioUrl) audioPlayers.append(audioPlayer) } catch { print("エラー") } } audioPlayer.delegate = self audioPlayer.prepareToPlay() // サウンドボタンを量産 button for index in 0..<soundArray.count { let soundButton = UIButton() soundButton.frame = CGRect(x: 20, y: 40 + (index * 30), width: 40, height: 30) soundButton.backgroundColor = UIColor.lightGray soundButton.titleLabel?.font = UIFont.systemFont(ofSize: 10) soundButton.setTitle("▶", for: .normal) soundButton.setTitleColor(UIColor.darkGray, for: .normal) soundButton.tag = index // ボタン識別用ID soundButton.addTarget(self, action: #selector(buttonEventSound(sender:)), for: .touchUpInside) soundButtons.append(soundButton) self.view.addSubview(soundButton) } } //viewDidLoadを閉じる // ボタンイベント音再生 func buttonEventSound(sender: UIButton) { let index = sender.tag if (audioPlayers[index].isPlaying){ audioPlayers[index].stop() audioPlayers[index].currentTime = 0 } else{ for i in audioPlayers { if (i.isPlaying) { i.stop() i.currentTime = 0 } } audioPlayers[index].play() } } // 音楽再生が成功した時に呼ばれるメソッド func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) { print("音終了") } // デコード中にエラーが起きた時に呼ばれるメソッド func audioPlayerDecodeErrorDidOccur(_ player: AVAudioPlayer, error: Error?) { print("デコードエラー") } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } }
その他のソースコード
import UIKit class PageViewController: UIPageViewController, UIPageViewControllerDataSource { var selectedIndex: Int = 0 // タップされたセルのindex var pageIndex:Int = 0 // 各ページに割り当てたindex var contentVCs = [UIViewController]() // ページングするviewControllerを格納する配列 override func viewDidLoad() { super.viewDidLoad() // ナビゲーションバーの透過を無効にする。 self.navigationController!.navigationBar.isTranslucent = false dataSource = self for index in 0..<20 { let contentVC = storyboard?.instantiateViewController(withIdentifier: "PageContentViewController") as! PageContentViewController contentVC.pageIndex = index contentVCs.append(contentVC) } self.setViewControllers([contentVCs[selectedIndex]], direction: .forward, animated: true, completion: nil) } // viewDidLoad()を閉じる // MARK: - UIPageViewControllerDataSource // スワイプでページを戻る(Before) func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? { guard let index = contentVCs.index(of: viewController as! PageContentViewController), index > 0 else { return nil } let previousVC = contentVCs[index - 1] return previousVC } // スワイプでページを進む(After) func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? { guard let index = contentVCs.index(of: viewController as! PageContentViewController), index < contentVCs.count - 1 else { return nil } let nextVC = contentVCs[index + 1] return nextVC } }
import UIKit class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { let sectionTitle = ["Title"] //セクションに表示するデータ let section0 = Array(1...20) //セルに表示するデータ @IBOutlet weak var tableView: UITableView! override func viewDidLoad() { super.viewDidLoad() tableView.delegate = self tableView.dataSource = self } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } func numberOfSections(in tableView: UITableView) -> Int { return sectionTitle.count } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return section0.count } func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { return sectionTitle[section] } func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { return 30 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) cell.textLabel?.text = "(section0[indexPath.row])" return cell } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if segue.identifier == "ToPageViewController" { if let indexPath = self.tableView.indexPathForSelectedRow { tableView.deselectRow(at: indexPath, animated: false) if let pageViewController = segue.destination as? PageViewController { pageViewController.selectedIndex = indexPath.row } } } } }
試したこと
クラッシュするページでurlまでは取得できているのですが、audioPlayerのところからnilになり(エラーチェックでエラーがあるならnilが入るようにしている)、デバックエリアに [Error The operation couldn\U2019t be completed. (NSOSStatusErrorDomain error -42.)] と出力されます。
エラーチェックでnilが入るコード関連を消すと、1ページ分多くめくったところで、AppDelegateのクラス宣言ところに [Thread1: signal SIGABLT] と表示され、デバックエリアには [libc++abi.dylib: terminating with uncaught exception of type NSException] と出力されています。
補足情報(FW/ツールのバージョンなど)
Swift3
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/07/11 04:47 編集