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

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

ただいまの
回答率

90.47%

  • Swift

    8935questions

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

swift UserDafaultsで保存したデータを他のViewControllerに持ってくる

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 305

globalplus

score 36

SecondViewControllerにUISliderを置いてそれによって音量を変更出来、FirstViewControllerにあるアラームの音量に反映させたいと考えています。その為にユーザが設定した音量(UISliderの値)をUserDafaultsを使ってFirstViewControllerに持って来たんですがエラー(Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0))に遭遇したため質問させて頂きます。
理想はUISliderで入力した数値をアラームの音量として使いたいです。(iPhoneの設定->サウンドと触覚->着信音と通知音のSliderが理想です。ライブラリは見つからなかった泣)
お手数ですがどうかよろしくお願いします。

import UIKit
import AVFoundation

class FirstViewController: UIViewController, AVAudioPlayerDelegate, UITableViewDelegate, UITableViewDataSource{

    let TODO = ["a", "b", "c", "d"]
    //アラームのリストです
    let volumeSlider = UISlider() as! SecondViewController
    //Cast from 'UISlider' to unrelated type 'SecondViewController' always failsという警告が出ています。自分なりに書いてみましたがこれがダメなんでしょうか?
    var volume: Float = 0
    var counter = 0
    var timer = Timer()
    var startTime:Double = 0.0
    var audioPlayer: AVAudioPlayer!
    @IBOutlet weak var tableView: UITableView!

    @IBAction func firstSwitch(_ sender: UISwitch)
    {
        if (sender).isOn
        {
            timer = Timer.scheduledTimer(withTimeInterval: 1 * 1, repeats: false, block: { timer in

                self.audioPlayer.volume = self.volumeSlider.value(forKey: "DateStore") as! Float
                //自分で書いてみました

                self.audioPlayer.play()

                self.audioPlayer.numberOfLoops = -1
                print(self.audioPlayer.isPlaying)
            })
        }else{
            timer.invalidate()
            print("switch1stopped")
            self.audioPlayer.stop()
        }
    }
import UIKit
import AVFoundation

class SecondViewController: UIViewController {

    var audioPlayer: AVAudioPlayer!

    let userDefaults = UserDefaults.standard
    let str = Float()
    @IBOutlet weak var volumeSlider: UISlider!
    @IBOutlet weak var volumeLabel: UILabel!
    @IBAction func volumeChange(_ sender: UISlider)
    {
        volumeLabel.text = String(Int(sender.value))
        volumeSlider.value = sender.value
        audioPlayer.volume = volumeSlider.value
        userDefaults.set(str, forKey: "DataStore")
        audioPlayer.play()
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?)
    {
        if segue.identifier == "endSetting"
        {
            let SecondViewController = segue.destination as! SecondViewController
            SecondViewController.volume = volumeSlider.value
        }
    }//値渡しの方法が分からなかったのでsegueをviewcontrollerごと繋いでみました
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

+1

おそらく下記の部分を変更すればいけると思います。

変更前

self.audioPlayer.volume = self.volumeSlider.value(forKey: "DateStore") as! Float

変更後

let userDefaults = UserDefaults.standard
self.audioPlayer.volume = userDefaults.object(forKey: "DateStore") as! Float

あとは、UserDefaultsはAny?で返ってくるので、letで定義した方が安全かなとは思いました。

let userDefaults = UserDefaults.standard
if let volume:Float = userDefaults.object(forKey: "DateStore") as? Float{
  self.audioPlayer.volume = volume
}

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/10/12 10:24

    ご回答ありがとうございます。試した結果アラームは鳴るようになったのですがUISliderで入力した値ではなくmp3ファイルそのものの音量で流れてしまっています。自分でself.audioPlayer.volume = volumeの所が
    self.audioPlayer.volume = volumeSlider(UISliderです).volumeかなと思い、でやってみたのですが他のviewcontrollerで宣言したオブジェクトを今のviewcontrollerで使う方法を知らないので困っています。エラーログはUse of unresolved identifier 'volumeSlider'となっています。
    ご回答頂けたら嬉しいです。
    ちなみにどうでも良いですが僕の本名も拓也です笑

    キャンセル

  • 2018/10/12 13:47

    うーん。他のviewControllerから値を取得するというのは基本やらないです。
    viewContoller内で完結する処理を書くのが理想で
    値を渡すとしたら、init処理時に指定するか、realmやuserDefaultsなどで取得するとか、クロージャ使うとか、何を実現したいかによって色々な方法があります。

    今回の場合UserDefaultsで問題なくできると思いますよ。もう少し詳しく見て欲しいのですが、
    audioPlayerのvolumeは0.0 - 1.0 なので、UISliderで設定している値もこの値になっていますか?
    https://developer.apple.com/documentation/avfoundation/avaudioplayer/1389330-volume

    キャンセル

  • 2018/10/12 13:50 編集

    ```
    if let volume:Float = userDefaults.object(forKey: "DateStore") as? Float{
    debugPrint(volume)
    self.audioPlayer.volume = volume
    }
    ```

    キャンセル

  • 2018/10/12 14:33

    UISliderの値を0-1に変更しましたが音量は同じです。
    もしかしたらUISliderから指を離した時に音楽が止まるコードを書いていないせいですかね?(どうやって書いたら良いか分からないので放置してました。なので毎回確認する時は音楽全て(16秒)を最後まで聞いてますアホなのは分かってます)

    キャンセル

  • 2018/10/12 17:41

    class FirstViewController {

    NotificationCenter.default.addObserver(self,
    selector: #selector(volumeChange),
    name: "test",
    object: nil)


    func volumeChange() -> Void {
    self.audioPlayer.start()
    self.audioPlayer.stop()
    }
    }


    class SecondViewController{
    NotificationCenter.default.post(name:"test", object: nil)
    }


    それであればNotificationCenterを使えばできるはずです。

    キャンセル

  • 2018/10/12 17:45

    今更ですが、
    FirstとSecondでControllerを分けたことによって実現したいこと
    が僕自身いまいち理解できていないので場当たり的なアドバイスになっているかもです。

    キャンセル

  • 2018/10/13 16:35

    わかりやすいご回答本当にありがとうございます。
    実現したい事はSecondにある音量バー(UISlider)で設定した音量をFirstのアラームが鳴った時の音量として使いたいです(iPhoneの設定にある音量設定と全く同じ仕様です)
    上記のNotificationcenter実装してみたのですが以前うまくいかずです、、
    思ったのがそもそもUISliderで入力した値は音量の値ですよっていうコードかいてないからですかね?
    UISliderは音量の他に拡大とか色々使い道があると思うので今回は音量で使うよ!っていうコード(宣言?)みたいなものを書いていないからかなと思いますがどうでしょうか?

    キャンセル

  • 2018/10/15 23:57

    もう一度ソース読んだのですがここかもです
    @IBAction func volumeChange(_ sender: UISlider)
    {
    volumeLabel.text = String(Int(sender.value))
    volumeSlider.value = sender.value
    audioPlayer.volume = volumeSlider.value
    userDefaults.set(str, forKey: "DataStore")
    audioPlayer.play()
    }
    これだとstrに何もセットされていないので
    @IBAction func volumeChange(_ sender: UISlider)
    {
    str = sender.value
    userDefaults.set(str, forKey: "DataStore")
    }
    とかにしないと行けないかと。

    キャンセル

  • 2018/10/15 23:59

    > 思ったのがそもそもUISliderで入力した値は音量の値ですよっていうコードかいてないからですかね?
    swiftは基本的に型があっていれば、「音量の値ですよ」とは言わなくていいです。
    audioPlayer.volumeはFloatで間違い無いので、その可能性は低いかと。

    キャンセル

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

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

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

  • Swift

    8935questions

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