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

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

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

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

Swift

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

Q&A

解決済

AVAudioPlayerの使い方

vlb
vlb

総合スコア109

Xcode

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

Swift

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

3回答

2グッド

0クリップ

640閲覧

投稿2019/01/03 15:16

編集2019/01/22 23:29

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

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

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

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

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

swift

1import UIKit 2import AVFoundation 3 4class ViewController: UIViewController { 5 6 override func viewDidLoad() { 7 super.viewDidLoad() 8 } 9 10 override func didReceiveMemoryWarning() { 11 super.didReceiveMemoryWarning() 12 } 13 14 let cymbalPath = Bundle.main.bundleURL.appendingPathComponent("cymbal.mp3") 15 16 //////////ここでインスタンスを生成////////// 17 var cymbalPlayer = AVAudioPlayer() 18 19 @IBAction func cymbal(_ sender: Any) { 20 do { 21 //////////ここでイニシャライザを指定////////// 22 cymbalPlayer = try AVAudioPlayer(contentsOf: cymbalPath, fileTypeHint: nil) 23 24 cymbalPlayer.play() 25 } catch { 26 print("error") 27 } 28 } 29}

swift

1class A { 2 init(string: String){ 3 } 4} 5 6var a = A() 7a = A(string: "~~~")

環境
xcode:10
swift:4.2

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

dja, techiro👍を押しています

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

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

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

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

  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

回答3

1

自己解決

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

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

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

投稿2019/01/23 14:09

vlb

総合スコア109

dja👍を押しています

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

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

このような回答には修正を依頼しましょう。

回答へのコメント

melan

2019/05/18 07:00 編集

私も同じような疑問を持っていたため、大変参考になりました。 以下のように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("シンバルでエラーが発生しました!") } } ```
melan

2019/05/18 11:05

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

0

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

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

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

swift

1//OK 2var cymbalPlayer = AVAudioPlayer() 3cymbalPlayer = AVAudioPlayer() 4 5//NG 6let cymbalPlayer = AVAudioPlayer() 7cymbalPlayer = AVAudioPlayer()

投稿2019/01/22 00:28

fuzzball

総合スコア16731

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

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

このような回答には修正を依頼しましょう。

回答へのコメント

vlb

2019/01/22 08:47

質問を訂正しました
fuzzball

2019/01/22 09:16 編集

>>インスタンスを生成した後に,イニシャライザのための引数を渡す 修正しても意味が分かりにくいですが、「(引数なしで)インスタンスを生成した後に、引数ありでインスタンスを生成しているのはなぜか?」ということでいいんでしょうかね。 おそらくですが、本来なら cymbalPlayer をOptional型にすべきところを、面倒くさいから「引数なしでインスタンスを生成」することで仮初期化しているだけでしょう。
vlb

2019/01/22 23:34

質問がわかりにくく,申し訳ありません。再度訂正しました. cymbalPlayerをOptional型にすべき、というのは、 var cymbalPlayer : AVAudioPlayer! にするべきということですか?
fuzzball

2019/01/23 00:43

もしくは var cymbalPlayer : AVAudioPlayer? です。 ! なら面倒臭さは無くなるので、そのコードを書いた人は ! を使いたくなかったのではないでしょうか。 もしくは、そもそもOptional型を理解していないか。
vlb

2019/01/23 06:55

私の質問としましては、 var cymbalPlayer : AVAudioPlayer! で、中身の入っていない変数cymbalPlayerを生成するのは納得がいくのですが、 var cymbalPlayer = AVAudioPlayer() で、変数cymbalPlayerを生成するのは理解出来ない、という事です。 理由としては、質問にあるように、AVAudioPlayerはイニシャライザとして「contentsOf:」を設けているので,インスタンス生成時に引数を渡す必要があると認識しているからです。
fuzzball

2019/01/23 07:07 編集

>>生成するのは理解出来ない 私は「仮初期化しているだけでしょう」と書きましたが、それが理解できないということですか? それとも他の意味ですか?
vlb

2019/01/23 09:00 編集

例えば, //////////////////////////////////////// class A { init(name: String) { } } var a: A? a = A(name: "~~~") //////////////////////////////////////// 上のコードは理解できるのですが, //////////////////////////////////////// class A { init(name: String) { } } var a = A() a = A(name: "~~~") //////////////////////////////////////// は,理解できない. ということです. 2つ目のコードは明らかに間違っていますよね? ならば //////////////////////////////////////// open class AVAudioPlayer : NSObject { public init(contentsOf url : URL) throws //以下略 } var cymbalPlayer = AVAudioPlayer() cymbalPlayer = try AVAudioPlayer(contentsOf : ~~~) //////////////////////////////////////// このコードも間違っているのではないですか?
fuzzball

2019/01/23 09:03

もう一つの質問でも同じようなコメントをしましたが、init()を実装すればいいだけの話です。(あちらではoverrideですが) コメントを読んでいないのか、理解できないのか、どちらでしょうか?
vlb

2019/01/23 09:11

先ほど書いたコードを見てもらえればわかると思うのですが, AVAudioPlayerクラスには,引数なしのイニシャライザ ”init()”は宣言されていないよに見えるのですが,私は何か勘違いをしているのでしょうか.
fuzzball

2019/01/23 09:15

それについてもがコメントしていますし、init()が無いならビルド時にエラーになるでしょう?
vlb

2019/01/23 09:18

init()がないのにビルド時にエラーにならないので,疑問に思って質問しているのですが,,,
MasakiHori

2019/01/23 09:22

クラスの継承関係を見落としているか、継承というものを知らないようです。 AVAudioPlayerはNSObjectのサブクラスでNSObjectがinit()を持っています。
vlb

2019/01/23 09:32

//////////////////////////////////////// class A { init() { } } class B : A { init(name: String) { } } var b = B() //エラー箇所 //////////////////////////////////////// 「引数がないぞ」 とエラーが吐かれます. 継承元にinit()があってもダメみたいですが.
fuzzball

2019/01/23 09:40

だからoverrideしろってあっちの質問で言ってるでしょ。 ここまで突っ込んだ話をするなら、少しは言語仕様を勉強して下さい。
MasakiHori

2019/01/23 09:44

をー、ごめん。 Objective-Cで書かれたクラスは特別なの。 が正しいですね。
fuzzball

2019/01/23 09:50

いや、Objective-Cは関係なくて、イニシャライザの継承の話かと。
MasakiHori

2019/01/23 09:54

質問者はAVAudioPlayer()が出来てしまうのが疑問てあたりになってるんじゃないの?
fuzzball

2019/01/23 10:03

そうです。で、(実際の実装は分からないけど)とりあえずinit()をoverrideすればエラーにならないですよって話になっているのですが。 何かObjective-C絡みの仕掛けがあるなら書いていただけると。(新規回答ででも)
vlb

2019/01/23 10:18 編集

>>MasakiHoriさん Objective-Cで書かれたものは, 引数なしのinti()が宣言されていなくても,引数なしのインスタンスが生成できるということでしょうか? それとも,override init() と記述がなくても,引数なしのインスタンスが生成できるということでしょうか? >>fuzzballさん あくまで例として出したAクラスやBクラスにoverrideと書けば引数を渡さずにインスタンスを生成できるのはわかります. 私は,AVAudioPlayer()には引数なしのinit()が宣言されているわけでもなければ,override init() が書かれているわけでもないのに,なぜ引数なしのインスタンスが生成でいるのか疑問に思っている次第です.
fuzzball

2019/01/23 10:18

あなたはAVAudioPlayerのソースコードを見たことがあるんですか?
vlb

2019/01/23 10:25 編集

先ほども書きましたが, //////////////////////////////////////// @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 //長いので以下略 //////////////////////////////////////// となっていると思いますが,
fuzzball

2019/01/23 10:33

なるほど、そこで判断されましたか。そこに無いから実装も無いのかどうかは知りませんし、今は調べる環境もないので、ひとまずMasakiHoriさんの返信を待ってみましょうか。
vlb

2019/01/23 10:41

>>fuzzballさん それがよさそうですね.
MasakiHori

2019/01/23 13:00

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

2019/01/23 14:06

なるほど,ありがとうございます. Objective-Cについての知識はなかったのですが,Objective-Cではそういう仕様なのですね.
MasakiHori

2019/01/23 14:11

どこかで読んだ気がするんですが、どこだったか全く思い出せない。 何点か覚えているのは、 1、Swiftのバグととらえている人もいた。 2、ドキュメント化されてないので突然なくなってもおかしくない。 あたりですかね。 なので質問者さんの「使えるのはおかしい」という感覚は正しいです。
vlb

2019/01/23 14:19

勉強になります. もう少しswiftの知識がついたら,Objective-Cなど色々な事を学んでみようと思います. ありがとうございました.
fuzzball

2019/01/24 00:28 編集

>>vlbさん(19:24へのコメント) あっちにも書きましたが、NSObjectで public init() と定義されている(外から見えている)のでinit()を呼べてもおかしくないと思います。 >>MasakiHoriさん Objective-Cで書かれているのなら、イニシャライザ(というかinit関数)は継承されるのでは?(継承されないのはSwiftの仕様ですよね?)
MasakiHori

2019/01/24 01:00

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

2019/01/24 01:03

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

2019/01/24 01:19

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

0

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)

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

swift

1import UIKit 2import AVFoundation 3 4class ViewController: UIViewController { 5 6 var player: AVAudioPlayer! 7 8 override func viewDidLoad() { 9 super.viewDidLoad() 10 // Do any additional setup after loading the view, typically from a nib. 11 12// var player = AVAudioPlayer() 13 14 let musicPath = Bundle.main.bundleURL.appendingPathComponent("music.mp3") 15 16 do { 17 try player = AVAudioPlayer(contentsOf: musicPath, fileTypeHint: nil) 18 player.play() 19 } catch { 20 print(error) 21 } 22 } 23 24 25}

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


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

swift

1// シンバル用のプレイヤーインスタンスを作成 2var cymbalPlayer = AVAudioPlayer() 3 4@IBAction func cymbal(_ sender: Any) { 5do { 6// シンバル用のプレイヤーに、音源ファイル名を指定 7cymbalPlayer = try AVAudioPlayer(contentsOf: cymbalPath, fileTypeHint: nil)

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

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

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

投稿2019/01/04 08:26

編集2019/01/04 12:20
izkn

総合スコア1698

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

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

このような回答には修正を依頼しましょう。

回答へのコメント

vlb

2019/01/21 14:30 編集

回答ありがとうございます. 問題を修正させていただきました.
hameji001

2019/01/04 10:32 編集

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

2019/01/21 14:33 編集

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 ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.83%

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

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

質問する

関連した質問

同じタグがついた質問を見る

Xcode

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

Swift

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