9683
初めまして。  
swiftを勉強し始めて1週間の初心者です。（プログラミングの経験もかなり浅いです。）

先ほど「世界一受けたいiPhoneアプリ開発の授業」という本を元にコードの写経をしていたところ、コンパイルエラーが出てしまいました。  
1〜2時間ほど考えてみたり、コードを打ち直してみたり、Xcodeを再起動してみたり、色々試しましたがエラーは消えず…。という状態です。

エラーでは

> Value of Optional type "AVAudioPlayer" not unwrapped; did you mean to  
>  use "!"or"?"?

エラーを治すための指示は

> Fix-It Insert "!"

と書いてありますが、!を挿入してもエラーが出たままです。逆に?を挿入したらエラーは無くなるんですが、これってどういうことが原因なのでしょうか？

コードは下記になります。（冒頭のcopyrightなどは省略させていただきます。**で囲まれたところにエラーが出ます。）

```

    import UIKit
    
    import AVFoundation //AVFoundationをインポートする
    
    class ViewController: UIViewController {
        var player:AVAudioPlayer?  //音声を制御するための変数
    
        //BGM再生メソッド
        func play(soundName:String){
        //String型の引数からサウンドを読み込む
            let soundPath = NSBundle.mainBundle().bundlePath.stringByAppendingPathComponent(soundName)
    
        //読み込んだファイルにパスをつける
            let url:NSURL? = NSURL.fileURLWithPath(soundPath)
        //playerに読み込んだmp3ファイルへのパスを設定する
            player = AVAudioPlayer(contentsOfURL: url, error: nil)
            player?.numberOfLoops = -1 //BGMを無限にループさせる
            **player.prepareToPlay() //音声を即時再生させる**
            player?.play() //音を再生させる
        }
    
        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view, typically from a nib.
    
            //playファイルの呼び出し、引数はファイル名
            play("BMG.mp3")
        }
    
        @IBAction func wineTapped(sender:UIButton){
    
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
            // Dispose of any resources that can be recreated.
        }
    
    }
    
```

ちなみに、これはコードの問題じゃないのかもしれませんが、上記コードの**で囲まれた部分を修正してエラーがない状態にしても、シミュレーターを立ち上げた際にうまく立ち上がってくれません。

なお、Xcodeのバージョンは6.3.1（6D1002）です。

何か解決策があれば教えて下さい。

宜しくお願い致します。
CC BY-SA 3.0
2015-04-30T00:28:56.163
9674
2015-04-30T09:07:04.053
2015-04-30T08:42:07.573
7362
9542
question
ios swift xcode6 ios8
音声即時再生のためのコード.prepareToPlay( )をコードに入れたところ、コンパイルエラーが出てしまいました。
エラーを出さないようにする訂正のしかたは、

```

    player?.prepareToPlay()
    
```

が正解です。

Swiftにおけるオプショナル（Optional）型について、きっちり勉強なさって、理解するようにしてください。Appleが開発言語をObjective-
CからSwiftに変更した理由の、半分以上がこのOptional型にあるといっても、過言ではないので。  
Optional型は、nilが代入されることを許容する変数の型をいいます。裏返しに表現すると、一般の変数（非Optional型）は、nilを許容しません。代入しようとした値がnilだったら、プログラムエラーになり、アプリ全体が落ちます。  
変数がnilを許容しないとはどういうことかというと、プログラム内のバグが潜む場所を、減らしていこうという意図です。iOSのフレームワークを、今後使っていくとわかってきますが、処理に失敗すると、返り値をnilとするメソッドが多数あります。そういうメソッドの後、返り値がnilかそうでないかで、条件分岐したプログラムを書いていれば、堅牢なプログラムに近づくんでしょうが、現実には、「ここでnilなんて、返ってこないでしょ？」ですましているプログラムが多数あります。そういう局面で、ちゃんと条件分岐するよう、プログラマに促す意味が、Optional型にあります。  
なので、Optional型を生かすようなプログラムにするなら、こういうコードになるでしょう。

```

    func play(soundName:String){
        let soundPath = NSBundle.mainBundle().bundlePath.stringByAppendingPathComponent(soundName)
        let url:NSURL? = NSURL.fileURLWithPath(soundPath)
        player = AVAudioPlayer(contentsOfURL: url, error: nil)
        // Optional Chainingを使う。
        if let thePlayer = player {
            thePlayer.numberOfLoops = -1
            thePlayer.prepareToPlay()
            thePlayer.play()
        }
    }
    
```

`if let thePlayer = player {}`は、ただの条件文ではなく、 **Optional Binding**
という特殊な構文です。Optional型の変数`player`の値が、nilでなければ、Unwrapした値を、非Optional型の変数`thePlayer`に代入します。（`else
{}`を追加すると、`player`がnilだったときの処理を行えます。）
CC BY-SA 3.0
2015-04-30T04:43:37.703
9683
2015-04-30T09:07:04.053
2015-04-30T09:07:04.053
7362
7362
9674
answer