70794


Swiftで以下のコードを試してみました。([参考にしたコード](https://github.com/zhiyao92/PickerView-on-
AlertController/blob/master/Picker%20View%20Alert%20Controller/ViewController.swift))

[code]

    import UIKit
    
    class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
    
        //ユーザー設定
        let userDefaults = UserDefaults.standard
    
        var choices = ["Toyota","Honda","Chevy","Audi","BMW"]
        var pickerView = UIPickerView()
        var typeValue = String()
    
        
        override func viewDidLoad() {
            super.viewDidLoad()
            
            self.userDefaults.register(defaults: ["pickerviewSelectRow": 0])
        }
        
        //MARK - PickerView
        
        func numberOfComponents(in pickerView: UIPickerView) -> Int {
            return 1
        }
    
        func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
            return choices.count
        }
        
        func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
            return choices[row]
        }
        
        func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
            if row == 0 {
                typeValue = "Toyota"
            } else if row == 1 {
                typeValue = "Honda"
            } else if row == 2 {
                typeValue = "Chevy"
            } else if row == 3 {
                typeValue = "Audi"
            } else if row == 4 {
                typeValue = "BMW"
            }
            self.userDefaults.set(row, forKey: "pickerviewSelectRow")
            self.userDefaults.synchronize()
        }
    
        //MARK - UIAlertController
        
        @IBAction func showChoices(_ sender: Any) {
            let alert = UIAlertController(title: "Car Choices", message: "\n\n\n\n\n\n", preferredStyle: .alert)
            //alert.isModalInPopover = true
            
            let pickerFrame = UIPickerView(frame: CGRect(x: 5, y: 20, width: 250, height: 140))
            
            
            let pickerviewSelectRow = self.userDefaults.object(forKey: "pickerviewSelectRow") as! Int
            pickerFrame.selectRow(2, inComponent: 0, animated: true) // 初期値 liveStreamPickerViewSelect
            
            pickerFrame.dataSource = self
            pickerFrame.delegate = self
            alert.view.addSubview(pickerFrame)
    
            alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
            alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (UIAlertAction) in
                
                print("You selected " + self.typeValue )
            
            }))
            self.present(alert,animated: true, completion: nil )
        }
    }
    
[/code]

userdefaultに値は保存されてはいるようなのですが、「Honda」などを選択してpickerviewを閉じたあとに、初期値を`selectRow`で指定しても毎回「Toyota」でpickerviewが起動してしまいます。

何が原因でしょうか？


CC BY-SA 4.0
2020-09-29T01:16:48.357
70792
2020-09-29T02:22:56.030
36446
question
swift
UIPickerViewの初期値をuserdefaultに保存し、適用したい


> 何が原因でしょうか？

`selectRow(_:inComponent:animated:)`を呼び出すタイミングの問題でしょう。

私が試したところ、`dataSource`を設定した後なら動作するようです。

[code]

            pickerFrame.dataSource = self
            pickerFrame.selectRow(2/*pickerviewSelectRow*/, inComponent: 0, animated: true) // 初期値
            pickerFrame.delegate = self
            alert.view.addSubview(pickerFrame)
    
[/code]

`dataSource`が設定されるまで、`UIPickerView`には選択肢がいくつあるかもわからないので、その中のどれかを選択しろと言われても困ると言うことだろうと思います。

* * *

ちなみに`UIAlertController`のview階層を直接いじると言ったことはApple側は想定していないので、別のバージョンのiOSで試してもうまくいくか(動作確認はXcode
12.0.1)は保証できません。

確実に動作させたい場合には、alertに似せた別画面(view controller)を作ってそれを表示してやると言ったことをしたほうがいいかもしれません。

* * *

ところで、あなたのコードでは現在`pickerView`なんてプロパティは全く使われていませんね。参考サイトのコードをコピペした状態のままなのでしょうが、コードが大きくなり複雑化してくるにつれ、そう言った使われてもいないプロパティ存在の弊害も大きくなっていくので、「もう使われていない」と分かった時点でさっさと削除してしまった方が良いでしょう。


CC BY-SA 4.0
2020-09-29T02:22:56.030
70794
2020-09-29T02:22:56.030
13972
70792
answer