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

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

ただいまの
回答率

90.01%

AVAudioPlayerの使い方

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,102

vlb

score 2

swift言語のAVAudioPlayerの使い方が分かりません.

1つ目のコードではAVAudioPlayerのインスタンスを生成した後に,音楽ファイルを指定しています.
しかし,AVAudioPlayerはイニシャライザとして「contentsOf:」を設けているので,インスタンス生成時に引数を渡す必要があると認識しています.

ど素人が,クラスが引数付きのイニシャライザを宣言しているにも関わらず,引数なしでインスタンスを生成した後に,引数ありのインスタンスを代入するという観点からみれば2つ目のコードと同じことをしているのではないかと思ってしまうのですが,もちろん間違っていることはわかります.

では,なぜ1つ目のコードにあるように,AVAudioPlayerは,引数付きのイニシャライザを宣言しているにも関わらず,引数なしのインスタンスを生成できるのでしょか

プログラミング初心者の自分でもわかるよう教えていただけると助かります.

import UIKit
import AVFoundation

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    let cymbalPath = Bundle.main.bundleURL.appendingPathComponent("cymbal.mp3")

    //////////ここでインスタンスを生成//////////
    var cymbalPlayer = AVAudioPlayer()

    @IBAction func cymbal(_ sender: Any) {
        do {
            //////////ここでイニシャライザを指定//////////
            cymbalPlayer = try AVAudioPlayer(contentsOf: cymbalPath, fileTypeHint: nil)

            cymbalPlayer.play()
        } catch {
            print("error")
        }
    }
}
class A {
    init(string: String){
    }
}

var a = A()
a = A(string: "~~~")

環境
xcode:10
swift:4.2

言葉足らずでしたらご指摘ください.

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

0

編集で追記した部分について。

なぜ1つ目のコードにあるように,AVAudioPlayerはインスタンスを生成した後に,イニシャライザを指定できるのでしょか

イニシャライザを指定できるという言い回しがちょっと意味不明なのですが、cymbalPlayerはvarで定義されているので、何度でもインスタンスを入れ直すことは出来ます。

//OK
var cymbalPlayer = AVAudioPlayer()
cymbalPlayer = AVAudioPlayer()

//NG
let cymbalPlayer = AVAudioPlayer()
cymbalPlayer = AVAudioPlayer()

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/01/24 10:00

    今はSwiftの文法上おかしくないですか?という話なのでobjcで書かれているものは特別が答えでいいのではないでしょうか? objcは(普通NSObjectを継承しているので)init()は明示的に書かない文化。 Swiftは objcヘッダからSwiftのgenerated interfaceを作る。 objcヘッダにinit()はない。 かといって使えないと問題がある。 objcは特別にしよう。ということです。 これ以上掘り下げると初心者の方は混乱すると思います。

    キャンセル

  • 2019/01/24 10:03

    ちなみに init() が使えるからといって安全かというと、クラスによっては実行時にクラッシュします。(原因は調べてません) なので質問者さんが参照したやり方は避けたほうがいいです。

    キャンセル

  • 2019/01/24 10:19

    うーん、まぁこの辺でやめておきます。
    そろそろついていけなくなってきているので。

    キャンセル

check解決した方法

-1

MasakiHoriさんのコメントで解決することができました.

Objective-Cで書かれていて継承ツリーの中にinit()があれば使えます。そう決まってます。 NSObjectにinit()があるのでNSObjectを継承していたら init() が使えます。

回答してくださった皆様,ありがとうございました.

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/05/18 15:54 編集

    私も同じような疑問を持っていたため、大変参考になりました。
    以下のようにletで書くとスッキリすると思いますので、ご参考まで。

    ```
    // シンバルの音源ファイルを指定
    let cymbalPath = Bundle.main.bundleURL.appendingPathComponent("cymbal.mp3")

    @IBAction func cymbal(_ sender: Any) {
    do {
    // シンバル用のプレイヤーに、音源ファイル名を指定
    let cymbalPlayer = try AVAudioPlayer(contentsOf: cymbalPath, fileTypeHint: nil)
    // シンバルの音源再生
    cymbalPlayer.play()
    } catch {
    print("シンバルでエラーが発生しました!")
    }
    }
    ```

    キャンセル

  • 2019/05/18 20:05

    すみません。上記のように記述すると、音が最後まで鳴りませんでした。
    やはりcymbalメソッドの外でcymbalPlayerをインスタンス化する必要がありそうです。

    キャンセル

-1

test environment

  • macOS Mojave 10.14.2
  • Xcode 10.1 Build version 10B61
  • Apple Swift version 4.2.1 (swiftlang-1000.11.42 clang-1000.11.45.1)

以下のように書くと理解しやすいかな。

import UIKit
import AVFoundation

class ViewController: UIViewController {

    var player: AVAudioPlayer!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

//        var player = AVAudioPlayer()

        let musicPath = Bundle.main.bundleURL.appendingPathComponent("music.mp3")

        do {
            try player = AVAudioPlayer(contentsOf: musicPath, fileTypeHint: nil)
            player.play()
        } catch  {
            print(error)
        }
    }


}

var player = AVAudioPlayer()はインスタンス生成というよりはプロパティの宣言と考える。
音を鳴らすにはインスタンスプロパティとして保持する必要があります。
var player = AVAudioPlayer()viewDidLoad()の中に書いてしまうと解放されてしまうので、音が鳴りません。二つ目のコードも同様です。


  「var player = AVAudioPlayer()はインスタンス生成というよりはプロパティの宣言と考える。」 とありますが,参考書では「// シンバル用のプレイヤーインスタンスを作成」となっており,どちらが正しいのか困惑しております.

// シンバル用のプレイヤーインスタンスを作成
var cymbalPlayer = AVAudioPlayer()

@IBAction func cymbal(_ sender: Any) {
do {
// シンバル用のプレイヤーに、音源ファイル名を指定
cymbalPlayer = try AVAudioPlayer(contentsOf: cymbalPath, fileTypeHint: nil)


参考書の方を採用してください。余生混乱させてしまいましたね。失礼いたしました。var player: AVAudioPlayer!と書いて初期化せず宣言だけの記述にした方が理解しやすいかと思ったのですが、参考書の説明の流れなら参考書を。

  「var player = AVAudioPlayer()をviewDidLoadの中に書いてしまうと解放されてしまう」 とありますが,解放とはなんでしょうか.

そのお使いの参考書に変数のスコープ、有効範囲について書かれている箇所はありますか。
AVAudioPlayerインスタンスを保持する変数をviewDidLoad()メソッドのローカル変数として定義するとメソッドの終了とともに変数も無くなります。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/01/04 18:58 編集

    回答ありがとうございます.

    問題を修正させていただきました.

    キャンセル

  • 2019/01/04 19:30 編集

    最初の質問から3つ目の質問は逸脱しています。

    きちんと、何がどうなっているか総論を習いたいなら、
    本(今読んでいるかもしれませんが。。。)もしくは
    スクールに通って、先生に聞くことをおすすめします。

    キャンセル

  • 2019/01/05 12:53 編集

    izknさん
    参考書に変数のスコープ、有効範囲について書かれている箇所はありません.


    hameji001さん
    回答ありがとうございます.
    AVAudioPlayerクラスのインスタンスを生成する際にはイニシャライザとして (contentsOf: , fileTypeHint: ) の部分を引数として渡す必要があると思うのですが,なぜインスタンスを生成する際に引数を渡さずにインスタンスを生成できるのか疑問に思っているところです.
    AVAudioPlayerは以下のようになっていると思うのですが,初心者の私からすると2つ目のコードと似ているように感じます.どの部分が異なるのでしょうか.
    ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
    @available(iOS 2.2, *)
    open class AVAudioPlayer : NSObject {

    public init(contentsOf url: URL) throws

    public init(data: Data) throws

    @available(iOS 7.0, *)
    public init(contentsOf url: URL, fileTypeHint utiString: String?) throws

    @available(iOS 7.0, *)
    public init(data: Data, fileTypeHint utiString: String?) throws
    ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

    キャンセル

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

  • ただいまの回答率 90.01%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる