

Xcode 12 で Swift を最近学び始めました。

下の画像にあるような赤いと黄色いエラーが出ました、ネットでいろいろ調べましたが解決策が分かりませんでした。このエラーを解決するにはどのようにすればよろしいのでしょうか？

**赤いエラー:**

[code]

    Cannot use instance member 'bottunPath' within property initializer; property initializers run before 'self' is available
    
[/code]

**黄色い警告:**

[code]

    'catch' block is unreachable because no errors are thrown in 'do' block
    
[/code]

* * *

**ソースコード:**

[code]

    import UIKit
    import AVFoundation
    
    class ViewController: UIViewController {
      
        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view.
            
        }
        
        let bottunPath =
            Bundle.main.bundleURL.appendingPathComponent("BOTTUN.mp3")
        var bottunPlayer = AVAudioPlayer(contentsOf: bottunPath, fileTypeHint: nil)
        
        @IBAction func BOTTUN(_ sender: Any) {
            do {
                bottunPlayer = try AVAudioPlayer(contentsOf: bottunPath, fileTypeHint: nil)
                
                bottunPlayer.play()
            } catch {
                print("BOTTUNでエラー")
            }
        }
    }
    
[/code]

[![画像の説明をここに入力](https://i.stack.imgur.com/hymfM.png)](https://i.stack.imgur.com/hymfM.png)


CC BY-SA 4.0
2021-07-02T00:59:27.560
77912
2022-12-28T22:02:35.387
2021-07-02T01:29:27.043
3060
47128
question
swift xcode12
Xcode で表示されたエラーを解決したい


> ネットでいろいろ調べましたが解決策が分かりませんでした。

そのような場合、ネットで調べてどのような情報を得て、何を試したのかを記載された方がいいでしょう。エラーメッセージの`Cannot use instance
member 'bottunPath' within property initializer; property initializers run
before 'self' is
available`でそのまま検索しても、あなたの場合にも当てはまる記事が多数見つかりました。もちろん日本語のものも多くあります。

* * *

で、そのエラーメッセージの後半は、なんでそんなことをエラーにするのか、と言ったSwiftコンパイラ作成陣からの言い訳なのであまり気にしないでください。

`Cannot use instance member 'bottunPath' within property initializer`

あなたのコードでは、2つのインスタンスプロパティ`bottunPath`と`bottunPlayer`を宣言していますが、そのうち`bottunPlayer`の初期化式(property
initializer)である`AVAudioPlayer(contentsOf: bottunPath, fileTypeHint:
nil)`の中で、別のインスタンスプロパティ`bottunPath`を使おうとしています。

**(Swift言語では)インスタンスプロパティ宣言時の初期化式の中で、別のインスタンスメンバー(instance member --
インスタンスプロパティやインスタンスメソッド)は使うことはできない**

これは、プログラミング言語としてのSwiftの決まりなので守ってやらないと仕方ありません。

* * *

具体的には、あなたのコードの場合、ボタンが押されるまで`bottunPlayer`には意味のある値は設定されないのですから、Optional型にしておくべきでしょう。

その他にも不適切なコードの書き方になっているところを改めるとこんな感じになります。

[code]

    import UIKit
    import AVFoundation
    
    class ViewController: UIViewController {
      
        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view.
            
        }
        
        //アプリ内リソースへのURL取得には普通`url(forResource:withExtension:)`を使う
        //間違えてたらクラッシュして知らせてほしい、と言う意味で意図的に強制アンラップ(`!`)を使用
        let buttonUrl = Bundle.main.url(forResource: "BUTTON", withExtension: "mp3")!
        //適切な初期値が設定できないなら、Optional型にしておく、初期値は自動的にnilとなる
        var buttonPlayer: AVAudioPlayer?
        
        //Swiftでは型名以外には大文字で始まる名称は使わない
        @IBAction func buttonTapped(_ sender: Any) {
            do {
                buttonPlayer = try AVAudioPlayer(contentsOf: buttonUrl, fileTypeHint: nil)
                
                //`buttonPlayer`をOptional型にしたので、Optional Chainingを使う
                buttonPlayer?.play()
            } catch {
                //エラーをキャッチした場合、そのエラーの情報を出さないとデバッグしにくい
                print("BUTTONでエラー:\(error)")
            }
        }
    }
    
[/code]

一度接続してしまったアクションメソッドの名前を書き換えるといろいろ苦労することになる(大抵の入門書には「間違えた場合の修正の仕方」はあまり書いていないです)んですが、いずれは身につけなければいけないことなので、思い切ってやって見たほうがいいかもしれません。

丸写しにするのではなく、参考にするつもりでやって見てください。

* * *

ちなみに2個目の警告は、1つ目のエラーのせいで一部の文が存在しないものと扱われて発生している(do-
catchの中にtryを使う文がない時の警告)ようです。まずはエラーを解消してみてください。


CC BY-SA 4.0
2021-07-02T03:53:42.563
77920
2021-07-02T03:53:42.563
13972
77912
answer