

swift4で書いていますが,異なるview間での値の受け渡しが上手くいきません。  
ViewController1に書いたtextをuserdefaultsに保存し、ViewController2のtableViewに表示する..という様に作りたいと考えています。  
fruitsという変数の中身を受け渡し、受け渡し先でuserdefaultsのkeyとして使用したいのですが、fruitsの受け渡しが上手くいかず、userdefaultsの読み込み,tableViewの表示ができません。fruitsはView上のUIボタンを押すことで中身が変わります。

[code]

    //ViewController1
    class ViewController1: UIViewController {
      var fruits: String = "apple"
      var Array: [String] = []
    ..中略..
          @IBAction func apple(_ sender: Any) {
            fruits = "apple"
          }
          @IBAction func banana(_ sender: Any) {
            fruits = "banana"
          }
    ..中略..
      let data = UserDefaults.standard 
      if let Array = data.stringArray(forKey: fruits ) {
        self.Array = Array
      }
      //保存ボタンを押したらArrayにappendする
      Array.append(myText)
      data.set(Array, forKey: fruits ) 
      data.synchronize()
    ..中略..
          override func prepare(for segue: UIStoryboardSegue, sender: 
          Any?) {
            if (segue.identifier == "toVC2") {
              let ViewController2 = (segue.destination as? 
              ViewController2)!
              ViewController2.fruits = self.fruits
            }
          }
    }
    
[/code]

遷移時に変数fruitsの中身がbananaなら、ViewController2に表示するセルにもuserdefaultsのkey:bananaのみ表示する、といったようにしたいと考えています。

[code]

    //ViewController2
    class ViewController2: UIViewController, UITableViewDelegate, 
    UITableViewDataSource {
      @IBOutlet weak var tableView: UITableView!
      var Array: [String] = []
      var fruits : String = ""
      override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        readData()
      }
      ..中略..
      func readData() { 
            let data = UserDefaults.standard
            if let Array = data.stringArray(forKey: fruits ) {
                self.Array = Array
        }
        tableView.reloadData() //cellの更新
      }
      ..中略..
      func tableView(_ tableView: UITableView, numberOfRowsInSection 
      section: Int) -> Int {
        return Array.count
      }
    
      func tableView(_ tableView: UITableView, cellForRowAt indexPath: 
      IndexPath) -> UITableViewCell {
        
        let cell: UITableViewCell = 
        tableView.dequeueReusableCell(withIdentifier: "Cell", for: 
        indexPath)
        cell.textLabel!.text = Array[indexPath.row]
        return cell
      }
    }
    
[/code]

質問を見てくださってありがとうございます。  
よく分かっていない部分も多いため、変なコードになっているかもしれません。  
回答お待ちしています。


CC BY-SA 4.0
2018-12-11T12:32:27.553
51120
2023-10-27T02:03:50.467
2021-07-08T15:00:09.710
3060
31401
question
swift xcode swift4
swift4 異なるview間での値の受け渡しについて


`DefaultsController`は`key`に対応する値を返すクラスなので、

[code]

    data.set(Array, forKey: fruits )
    
[/code]

と

[code]

    if let Array = data.stringArray(forKey: fruits )
    
[/code]

の`fruits`は同じ値(=`key`)でないと、期待したものが帰ってこないと思います。  
つまり、ある瞬間の`UserDefaults.standard`の中の状態は、

[code]

    --UserDefaults.standard--------------------
    |   key     |   value                     |
    |-----------+-----------------------------|
    | banana    |   @["banana"]               |
    |-----------+-----------------------------|
    | apple     |   @["banana", "apple"]      | 
    -------------------------------------------
    (orangeは未定義なので、nilが返されてしまう)
    
[/code]

の様に、配列に要素を追加していく度に、`key`（この場合は`fruits`という変数）を変化させてしまうと、`key`毎にデーターが作られてしまい、どれを取り出すのが正しいのか訳が分からなくなってしまうと思います。

なので、この場合の正解は、`ViewController1.swift`か`ViewController2.swift`ソースのどちらか一方に`import`文と`class`宣言の間に

[code]

    public let fruits: String = "fruits"
    
[/code]

と書き、`fruits`を定数にしてしまい、`ViewController1`,
`ViewController2`では、`fruits`への代入は行わない様にすれば良いと思います。

ここから余談

ただし、`UsersDefault`というのは名前からも解るとおり、アプリケーションの設定をアプリケーションが終了しても覚えておくための仕組みで、ユーザーデーターを管理するのは、独自ファイル、`CoreData`、`SQLite3`データベース、`Realm`データベースなど、他の仕組みを使うべきだと思います。


CC BY-SA 4.0
2018-12-12T03:44:16.983
51133
2018-12-12T03:44:16.983
14745
51120
answer