

Stringの配列をUserDefaultで保存し、再度読み込もうとしています。  
ただ現在、読み込んだ際にnilになってしまいエラーでアプリが落ちてしまいます。

Playgroundでコードで試しているのですがどうやったらStringの配列で保存、読み込みができるか教えてください

[code]

    import UIKit
    
    let str = ["aaa","iii","uuu"]
    
    let defauls = UserDefaults()
    
    defauls.set(str, forKey: "str")
    
    defauls.synchronize()
    
    //ここがエラーになる
    defauls.array(forKey: "str") as! [String]
    
[/code]


CC BY-SA 3.0
2017-03-23T16:47:53.457
33496
2017-05-02T10:46:29.350
2017-05-02T10:46:29.350
19110
21171
question
swift ios swift3
UserDefaultでStringの配列を保存する方法について


結論から言うと、メソッドの使い方は正しいのですが、「Playgroundでコードで試している」という試し方が間違っています。

**`UserDefaults`(Swift2までなら`NSUserDefaults`)が(PlatformをiOSとした)Playgroundでは動作しない**
と言う事象はXcode7の時代に報告されているのですが、現在の最新版Xcode(8.2.1)でも存続しているようです。

[NSUserDefaults no longer saving
values](https://forums.developer.apple.com/message/15663#15663)

("UserDefaults Playground"で検索すれば他にも多数の記事が見つかります。)

* * *

`UserDefaults`の使い方を(iOSで)試すのであれば、簡単なSingle Viewプロジェクトを作ってみてください。

[code]

    import UIKit
    
    class ViewController: UIViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view, typically from a nib.
            let strArr = ["aaa","iii","uuu"]
    
            let defauls = UserDefaults()
    
            defauls.set(strArr, forKey: "strArr")
    
            defauls.synchronize()
    
            //シミュレータ・実機ではエラーにならない
            print(defauls.array(forKey: "strArr") as! [String]) //->["aaa", "iii", "uuu"]
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
            // Dispose of any resources that can be recreated.
        }
    
    
    }
    
[/code]

文字列でもないものを`str`という名称の変数に入れるのは気持ちが悪いので`strArr`に変えてありますが、それ以外はあなたのコードと全く同じ内容です。

なお、上記のリンク先の記事にもありますが、このような使い方の場合、本当は`defauls.synchronize()`は不要です。

* * *

なお、`UserDefaults`からの値の取り出しは、様々な条件で`nil`になりうるわけですから、たとえ機能を試すためのお試しコードでも、`as!`のように「私のアプリをクラッシュさせて」型の演算子を使うのはお勧めできません。

[code]

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        let defauls = UserDefaults()
        if let defArr = defauls.array(forKey: "strArr") as? [String] {
            //アプリの2回目以降の実行時(UserDefaultsに値を設定済みの時)はこちらが走る
            print(defArr) //->["aaa", "iii", "uuu"]
        } else {
            //アプリの初回実行時(UserDefaultsが空の時)はこちらが走る
            print("Setting new array to 'defArr'")
            let strArr = ["aaa","iii","uuu"]
    
            defauls.set(strArr, forKey: "strArr")
        }
    }
    
[/code]

条件バインディングなどを上手く使って「`nil`安全」なコーディングを(ちょっとしたお試しコードを書くときでも)心がけた方がいいでしょう。


CC BY-SA 3.0
2017-03-23T21:41:18.267
33498
2017-03-23T21:41:18.267
13972
33496
answer