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

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

新規登録して質問してみよう
ただいま回答率
85.49%
TableView

TableView(UITableView)とは、リスト形式で表示するコントロールで、ほとんどのアプリに使用されています。画面を「行」に分けて管理し、一般的には各行をタップした際に詳細画面に移動します。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

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

Q&A

解決済

1回答

629閲覧

tableViewに新しい行を追加したい

yasumaro

総合スコア67

TableView

TableView(UITableView)とは、リスト形式で表示するコントロールで、ほとんどのアプリに使用されています。画面を「行」に分けて管理し、一般的には各行をタップした際に詳細画面に移動します。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

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

0グッド

1クリップ

投稿2018/11/10 13:02

前提・実現したいこと

swift4で入力画面(A)で記入した内容を別画面(B)tableViewに新たな行として追加したいです。
今の所セグエで入力画面完了後にtableViewの画面Bに遷移しています。

入力画面から送るデータは構造体で下記の様になります。これが一つの行のまとまりで、
このセットを何行か表示していきたいです。

struct NewData { var title :String var memo :UITextView var img :UIImageView var lebel :String }

完了ボタン押下後に実行される関数です。↓
上記の構造体をセグエで渡しています。

@IBAction func completeButtonAction(_ sender: Any) { performSegue(withIdentifier: "didCompleteAddTask", sender: nil) } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if segue.identifier == "didCompleteAddTask" { let listview:ListViewController = (segue.destination as! ListViewController) let newData:NewData = NewData(title:title memo:textView, img :selectedImage, lebel: selectedLebel) listview.oldData.append(newData)

↑上記にあるlistview:ListViewControllerは画面tableviewを表示するコントローラーです。
そのクラスにはプロパティとして構造体入力されたデータを格納する配列を宣言しています。
さらに表示するたtableviewのメソッドもあります。

class ListViewController: UIViewController ,UITableViewDelegate, UITableViewDataSource { @IBOutlet weak var tableView: UITableView! //タスク追加画面から受け取るためのパラメーター var oldData = [NewData]() 〜〜〜〜〜省略〜〜〜〜〜〜〜 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { //print(newData.title) return self.oldData.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) //print(indexPath.row) //表示内容 cell.textLabel?.text = oldData[indexPath.row].title cell.detailTextLabel?.text = oldData[indexPath.row].memo.text cell.imageView?.image = oldData[indexPath.row].img.image return cell }

長くなりましたがこれからつまずいているポイントです。

発生している問題

構造体を格納するためにプロパティで配列を作りどんどんappendで追加して表示させたいのです。
しかし、はじめに追加した一つのみ表示されるのですが、二つめ以降は追加されず置き換わってしまいます。

一つめ追加後、もう一度追加画面に移動し完了ボタンを押すと viewdidloadが読み込まれプロパティに保存していたものが消えてしまっている様な気がします。それともappendの仕方が間違っているのでしょうか?

ただしテーブルビューに一つだけ追加された行を押下し詳細画面(c)に行き戻ると残っています。
(ナビゲーションバーを利用。戻るとviewdidloadは実行されずviewwillappearが実行される)

追加画面(画面B)でキャンセルボタンを押すとセグエでtableview画面に戻る様にもしていますが
その時も追加していたものが無くなっています。

===============================

長くなりましたが下記の3つが疑問です。
①セグエで戻るとviewdidLoadでリセットされしまうのでしょうか?
②appendの使い方は正しいでしょうか?
③どのようにして画面テーブルビュー一覧画面に追加して行ける様になるのか(最終的に実現したいこと)
④realmでデータを保存し呼び出す様にしないとやはりできないのでしょうか?

swiftを勉強し始めて3か月のど素人です優しい言葉でお願いします。
≦(._.)≧ ペコ

念の為関係するファイルを記載します。
都合上関係のないコメントやスペースが入っています。

addTaskViewController.swift

import UIKit //構造体 struct NewData { var title :String var memo :UITextView var img :UIImageView var lebel :String } var willAddData = [NewData]() class addTaskViewController: UIViewController ,UITextViewDelegate,UIPickerViewDelegate,UIPickerViewDataSource,UIImagePickerControllerDelegate,UINavigationControllerDelegate{ @IBOutlet weak var memoPlaceHolder: UILabel! //以下4つがリストに送る値 @IBOutlet weak var textView: UITextView! @IBOutlet weak var lebelPicker: UIPickerView! @IBOutlet weak var selectedImage: UIImageView! var selectedLebel :String = "" var lebelDataList = ["1級","2級","3級"] override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. //self.navigationController?.setNavigationBarHidden(true, animated: false) textView.delegate = self } //ナビゲーションバーの非表示 override func viewWillAppear(_ animated: Bool) { self.navigationController?.setNavigationBarHidden(true, animated: false) } override func viewDidDisappear(_ animated: Bool) { self.navigationController?.setNavigationBarHidden(false, animated: false) } /**********************************************/ override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } /**********************************************/ //テキストフィールドをクリックした時 func textViewShouldBeginEditing(_ textView: UITextView) -> Bool { memoPlaceHolder.isHidden = true //print("クリックされました") return true } //テキストフィールドから外れた時,空だったら表示。 func textViewDidEndEditing(_ textView: UITextView) { if textView.text.isEmpty { memoPlaceHolder.text = "ここにメモを残せます。" memoPlaceHolder.isHidden = false } else { self.textView.text = textView.text } } /*********************************************************/ //UIPickerViewの設定 func numberOfComponents(in pickerView: UIPickerView) -> Int { return 1 } func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { return lebelDataList.count } func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? { return lebelDataList[row] } func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { self.selectedLebel = lebelDataList[row] } //画像を追加 @IBAction func addImageButtonAction(_ sender: Any) { print("クリックされた") let controller: UIAlertController = UIAlertController(title:"", message: "どの方法で写真を読み込みますか?", preferredStyle: UIAlertControllerStyle.actionSheet) //1つ目の選択肢 controller.addAction(UIAlertAction(title: "撮影する", style: UIAlertActionStyle.default, handler: { (hoge) in self.selectedCamera() })) //2つ目の選択肢 controller.addAction(UIAlertAction(title: "カメラロールから読み込む", style: UIAlertActionStyle.default, handler: { (action) in self.selectedLibrary() })) //3つ目キャンセル controller.addAction(UIAlertAction(title: "キャンセル", style: UIAlertActionStyle.cancel, handler: nil)) //UIControllerを表示 self.present(controller, animated: true, completion: nil) } func selectedCamera(){ //カメラが利用できるならば if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.camera) { //インスタンスを作成 let picker :UIImagePickerController = UIImagePickerController() picker.sourceType = UIImagePickerControllerSourceType.camera picker.delegate = self present(picker, animated: true, completion: nil) } } func selectedLibrary() { if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.photoLibrary) { let picker : UIImagePickerController = UIImagePickerController () picker.sourceType = UIImagePickerControllerSourceType.photoLibrary picker.delegate = self present(picker, animated: true, completion: nil) } } /***************************/ //画像の表示 func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) { selectedImage.image = info[UIImagePickerControllerOriginalImage] as? UIImage dismiss(animated: true, completion: nil) } /***************************/ //完了ボタン押下後のセグエ(セルに課題を追加する) @IBAction func completeButtonAction(_ sender: Any) { performSegue(withIdentifier: "didCompleteAddTask", sender: nil) } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if segue.identifier == "didCompleteAddTask" { let listview:ListViewController = (segue.destination as! ListViewController) let newData:NewData = NewData(title:"未定", memo:textView, img :selectedImage, lebel: selectedLebel) listview.oldData.append(newData) } }

2つめListViewController.swift

import UIKit class ListViewController: UIViewController ,UITableViewDelegate, UITableViewDataSource { @IBOutlet weak var tableView: UITableView! //タスク追加画面から受け取るためのパラメーター // var newData:NewData! var oldData = [NewData]() override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. tableView.delegate = self tableView.dataSource = self } override func viewWillAppear(_ animated: Bool) { self.navigationItem.hidesBackButton = true } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } func numberOfSections(in tableView: UITableView) -> Int { return 1 } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { //print(newData.title) return self.oldData.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) cell.textLabel?.text = oldData[indexPath.row].title cell.detailTextLabel?.text = oldData[indexPath.row].memo.text cell.imageView?.image = oldData[indexPath.row].img.image return cell }

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

addTaskViewController から ListViewController に遷移するときに ListViewController が生成されるので、oldData は遷移のたびに初期化されます。(ListViewController から addTaskViewController に戻った時点で ListViewController のインスタンスは解放されます)

入力されたデータは addTaskViewController 側で管理して、遷移するときに ListViewController に渡してやるのがいいと思います。

投稿2018/11/12 02:51

fuzzball

総合スコア16731

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yasumaro

2018/11/15 10:54

ご返信ありがとうございます。 >ListViewController のインスタンスは解放されます の部分が勉強不足で理解できませんでした。 >入力されたデータは addTaskViewController 側で管理して というのは過去に入力されたモノも、追加時に入力されたモノ同様 addTaskViewController 側で管理し遷移するたびに一緒に送るという認識出会っていますか? また >遷移するときに ListViewController に渡してやるのがいいと思います。 下記の方法だと遷移時に渡していることにはならないでしょうか? override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if segue.identifier == "didCompleteAddTask" { let listview:ListViewController = (segue.destination as! ListViewController) let newData:NewData = NewData(title:title memo:textView, img :selectedImage, lebel: selectedLebel) // listview.oldData.append(newData) Listview.oldData = newData
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問