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

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

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

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

Q&A

解決済

1回答

739閲覧

画面遷移時に配列に追加しCellを生成したい

coco7777

総合スコア8

Swift

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

0グッド

1クリップ

投稿2022/07/28 10:48

画面遷移をする時にtextFieldの値を渡し、配列に追加してTableViewcellに表示させたいです。
具体的にはnikkitableViewControllerで『+』ボタンを押すと、hennsyuViewControllerに遷移し
そこでtextFieldに入力します。その後『完了』ボタンを押すことでnikkitableViewControllerにある配列に追加して、画面遷移しCellを生成したいです。
3画面構成になっているのですが、nikkitableViewController→ hennsyuViewController→ nikkitableViewControlleの流れの時だけ配列に追加したいです。
コードを書いてみたのですがCellが生成されず困っています。
文字数の都合で2番目の画面コード以下に記載します。

swift

1import UIKit 2 3class nikkiTableViewController: UIViewController,UITableViewDelegate,UITableViewDataSource,UISearchBarDelegate{ 4 5 private let cellId = "cellId" 6 7 var addBarButtonItem:UIBarButtonItem! 8// var tableViewCell = nikkiTableViewCell() 9 10 var topImageArray = [UIImage]() 11 var nameArray = [String]() 12 var dateArray = [String]() 13 var hyoukaArray = [String]() 14 var textViewArray = [String]() 15 16 @IBOutlet weak var nikkiTableView: UITableView! 17 18 19 override func viewDidLoad() {super.viewDidLoad() 20 21 setupSearchBar() 22 23 addBarButtonItem = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(addBarButtonTapped(_:))) 24 addBarButtonItem.tintColor = UIColor.white 25 26 //navigationVarの右側に追加 27 self.navigationItem.rightBarButtonItem = addBarButtonItem 28 29 nikkiTableView.delegate = self 30 nikkiTableView.dataSource = self 31 32 let appearance = UINavigationBarAppearance() 33 appearance.configureWithOpaqueBackground() 34 appearance.backgroundColor = .rgb(red: 173, green: 216, blue: 230) 35 36 //標準の高さ 37 navigationItem.standardAppearance = appearance 38 //ナビゲーションバーが透過する 39 navigationItem.scrollEdgeAppearance = appearance 40 //標準の文字の大きさ 41 navigationItem.compactAppearance = appearance 42 43 let tapGesture = UITapGestureRecognizer( 44 target: self, 45 action: #selector(dismissKeyboard)) 46 view.addGestureRecognizer(tapGesture) 47 48 tapGesture.cancelsTouchesInView = false 49 50 51 } 52 53 54 func setupSearchBar(){ 55 56 if let navigationBarFrame = navigationController?.navigationBar.bounds { 57 let searchBar: UISearchBar = UISearchBar(frame: navigationBarFrame) 58 searchBar.delegate = self 59 searchBar.placeholder = "タイトルで探す" 60 searchBar.tintColor = UIColor.white 61 searchBar.keyboardType = UIKeyboardType.default 62 navigationItem.titleView = searchBar 63 navigationItem.titleView?.frame = searchBar.frame 64 65 } 66 } 67 68 69 70 @objc func dismissKeyboard() { 71 navigationItem.titleView?.endEditing(true) 72 } 73 74 func searchBarSearchButtonClicked(_ searchBar: UISearchBar) { 75 searchBar.resignFirstResponder() 76 } 77 78 func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { 79 80 return 190 81 } 82 83 func numberOfSections(in tableView: UITableView) -> Int { 84 85 return 1 86 } 87 88 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 89 90 return nameArray.count 91 92 } 93 94 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 95 96 let cell = nikkiTableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! nikkiTableViewCell 97 98 //cell.topImageView?.image = topImageArray[indexPath.row] 99 cell.nameLabel?.text = nameArray[indexPath.row] 100 cell.dateLabel?.text = dateArray[indexPath.row] 101 cell.hyoukaLabel?.text = hyoukaArray[indexPath.row] 102 103 104 return cell 105 106 } 107 108 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 109 110 let storyboard = UIStoryboard(name: "nikkiTableView", bundle: nil) 111 let textVC = storyboard.instantiateViewController(withIdentifier: 112 "textViewController") 113 //値、参照渡しのコードを書く 114 navigationController?.pushViewController(textVC, animated: true) 115 //タップした後、セルの色が白色に戻る 116 tableView.deselectRow(at: indexPath, animated: true) 117 118 navigationItem.titleView?.endEditing(true) 119 120 121 } 122 123 124 @objc func addBarButtonTapped(_ sender: UIBarButtonItem) { 125 126 let hennsyuVc = storyboard?.instantiateViewController(withIdentifier: "hennsyuViewController") as! hennsyuViewController 127 navigationController?.pushViewController(hennsyuVc, animated: true) 128 129 } 130 131 override func viewWillAppear(_ animated: Bool) { 132 133 nikkiTableView.reloadData() 134 135 // TODO: ①に戻ってきたらUITableViewを再描画します。 136 if AppState.isEdited { 137 // ③から完了をタップして戻ってきた場合は②に遷移します。 138 AppState.isEdited = false 139 let textvc = storyboard?.instantiateViewController(withIdentifier: "textViewController") as! textViewController 140 141 //textvc.nameField = nameArray 142 143 navigationController?.pushViewController(textvc, animated: true) 144 145 } 146 147 } 148 149} 150 151 152 class nikkiTableViewCell: UITableViewCell { 153 154 @IBOutlet weak var topImageView: UIImageView! 155 @IBOutlet weak var nameLabel: UILabel! 156 @IBOutlet weak var dateLabel: UILabel! 157 @IBOutlet weak var hyoukaLabel: UILabel! 158 159 override func awakeFromNib() { 160 super.awakeFromNib() 161 162} 163 override func setSelected(_ selected: Bool, animated: Bool) { 164 super.setSelected(selected, animated: animated) 165 166 } 167 168 169}

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

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

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

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

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

coco7777

2022/07/28 10:48

import UIKit import DKImagePickerController class hennsyuViewController: UIViewController,UIImagePickerControllerDelegate,UINavigationControllerDelegate,UITextFieldDelegate, UITextViewDelegate { var completButtonItem:UIBarButtonItem! @IBOutlet weak var textField: UITextView! @IBOutlet weak var dateField: UITextField! @IBOutlet weak var hyoukaField: UITextField! @IBOutlet weak var addressField: UITextField! @IBOutlet weak var nameField: UITextField! var photos: [UIImage] = [] // 実際に選択された枚数 var selectedCount = 0 let pickerController = DKImagePickerController() override func viewDidLoad() { super.viewDidLoad() dateField.delegate = self hyoukaField.delegate = self addressField.delegate = self nameField.delegate = self textField.delegate = self // checkpermission.checkCamera() let appearance = UINavigationBarAppearance() appearance.configureWithOpaqueBackground() appearance.backgroundColor = .rgb(red: 173, green: 216, blue: 230) navigationController?.navigationBar.tintColor = UIColor.white //標準の高さ navigationItem.standardAppearance = appearance //ナビゲーションバーが透過する navigationItem.scrollEdgeAppearance = appearance //標準の文字の大きさ navigationItem.compactAppearance = appearance completButtonItem = UIBarButtonItem(title: "完了", style: .done, target: self, action: #selector(completButtonTapped(_:))) self.navigationItem.rightBarButtonItem = completButtonItem dateField.setUnderLine() hyoukaField.setUnderLine() addressField.setUnderLine() nameField.setUnderLine() let toolBar = UIToolbar() toolBar.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 40) let spacer = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil) let kbDoneButton = UIBarButtonItem(title: "閉じる", style: .done, target: self, action:#selector(kbDoneTaped) ) toolBar.items = [spacer,kbDoneButton] textField.inputAccessoryView = toolBar } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) NotificationCenter.default.addObserver(self, selector: #selector(hennsyuViewController.keyboardShow(_:)), name: UIResponder.keyboardWillShowNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(hennsyuViewController.keyboardHide(_:)), name: UIResponder.keyboardDidHideNotification, object: nil) } @IBAction func addImageButton(_ sender: Any) { pickerController.maxSelectableCount = 5 //カメラモード、写真モードの選択 pickerController.sourceType = .photo //キャンセルボタンの有効化 pickerController.showsCancelButton = true //pickerController.UIDelegate = CustomUIDelegate() pickerController.didSelectAssets = { (assets: [DKAsset]) in print("didSelectAssets"); print(assets) //assetsのカウントがnilでないとき実行 // if assets.count > 0 { // // } } pickerController.modalPresentationStyle = .fullScreen present(pickerController, animated: true, completion: nil) } func textFieldShouldReturn(_ textField: UITextField) -> Bool { dateField.resignFirstResponder() hyoukaField.resignFirstResponder() addressField.resignFirstResponder() nameField.resignFirstResponder() return true } override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?){ self.view.endEditing(true) } @objc func keyboardShow(_ notification: Notification){ if !textField.isFirstResponder { return } if self.view.frame.origin.y == 0 { if let keyboardRect = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue { self.view.frame.origin.y -= keyboardRect.height } } } @objc func keyboardHide(_ notification: Notification){ if self.view.frame.origin.y != 0 { self.view.frame.origin.y = 0 } } @objc func kbDoneTaped (_ sender:UIButton){ self.view.endEditing(true) } //完了ボタンを押した時 @objc func completButtonTapped(_ sender: UIBarButtonItem){ if let n = navigationController, n.viewControllers[n.viewControllers.count - 2] is nikkiTableViewController { // ①から遷移してきた場合は完了をタップしたことを表すフラグを設定します。 AppState.isEdited = true } navigationController?.popViewController(animated: true) } override func viewWillDisappear(_ animated: Bool) { if AppState.isEdited { let nikkiVC = storyboard?.instantiateViewController(withIdentifier: "nikkiTableViewController") as! nikkiTableViewController nikkiVC.nameArray.append(nameField.text!) nikkiVC.dateArray.append(nameField.text!) nikkiVC.hyoukaArray.append(hyoukaField.text!) nikkiVC.textViewArray.append(textField.text!) } } }
guest

回答1

0

ベストアンサー

ちょっと質問欄に入りきらないほどのコードになってきてしまいましたね。
大変かもしれませんが、問題を再現できる最小のコードになるように、不要なコードを削除してからの方が良いかもしれません。
*解決したい問題と関係ないコードが含まれていると、回答者に問題が何か伝わらないかもしれませんので・・

https://stackoverflow.com/questions/19343519/pass-data-back-to-previous-viewcontroller/33229483#35759500

Stack Overflowを参考に、コールバックを使って配列にUITextFieldの内容を追加するコードを書いてみました。
新規追加の場合はコールバックを使うようにして(hennsyuViewControllerにコールバックを渡す)、変更の場合はコールバックを使わないようにする(hennsyuViewControllerにコールバックを渡さない)ようなイメージはいかがでしょうか。
*回答に記載したコードは変更の場合については省略してしまっています・・

// *****のようなコメントがポイントになると思います。

クラスは次のように読み替えてください。
*TableViewControllerはnikkiTableViewController
*TableViewCellはnikkiTableViewCell
*TwoViewControllerはhennsyuViewController

swift

1import UIKit 2 3class TableViewController: UITableViewController { 4 var array = [String]() 5 override func viewDidLoad() { 6 super.viewDidLoad() 7 let barButtonItem = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(action(_:))) 8 self.navigationItem.rightBarButtonItem = barButtonItem 9 for i in 0..<30 { 10 array.append("\(i)") 11 } 12 } 13 override func numberOfSections(in tableView: UITableView) -> Int { 14 return 1 15 } 16 override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 17 return array.count 18 } 19 override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 20 let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath) 21 if let c = cell as? TableViewCell { 22 c.label.text = array[indexPath.row] 23 } 24 return cell 25 } 26 override func viewWillAppear(_ animated: Bool) { 27 tableView.reloadData() 28 } 29 @objc func action(_ sender: UIBarButtonItem) { 30 let vc = storyboard?.instantiateViewController(withIdentifier: "twoViewController") as! TwoViewController 31 // ***** UITextField.textを受け取って処理するコールバックを設定します。 32 vc.callback = { s in 33 // UITextField.textを受け取って配列に追加します。 34 self.array.append(s) 35 } 36 navigationController?.pushViewController(vc, animated: true) 37 } 38} 39 40class TableViewCell: UITableViewCell { 41 @IBOutlet weak var label: UILabel! 42 override func awakeFromNib() { 43 super.awakeFromNib() 44 } 45 override func setSelected(_ selected: Bool, animated: Bool) { 46 super.setSelected(selected, animated: animated) 47 } 48} 49 50class TwoViewController: UIViewController { 51 @IBOutlet weak var textField: UITextField! 52 // ***** 「UITextField.textを受け取って処理するコールバック」を格納するための変数を定義します。 53 var callback: ((String) -> Void)? 54 override func viewDidLoad() { 55 super.viewDidLoad() 56 let barButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(action(_:))) 57 self.navigationItem.rightBarButtonItem = barButtonItem 58 } 59 @objc func action(_ sender: UIBarButtonItem) { 60 // ***** Doneをタップしたときにコールバックの処理を呼び出します。 61 if let text = textField.text, 62 !text.isEmpty { 63 callback?(text) 64 } 65 navigationController?.popViewController(animated: true) 66 } 67}

投稿2022/07/28 13:28

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

coco7777

2022/07/29 06:01

xg63ex2bさん 回答ありがとうございます >ちょっと質問欄に入りきらないほどのコードになってきてしまいましたね。 大変かもしれませんが、問題を再現できる最小のコードになるように、不要なコードを削除してからの方が良いかもしれません。 ご指導のおかげでなんとか少しずつですが目標に近づいています。いつもありがとうございます。 おしゃる通りですね。今後は回答してくださる方にも配慮した質問ができるようにしていきたいと思います。 コールバックというコードの書き方があるのですね。今調べてみて多少の理解はできました。ありがとうございます xg63ex2bさんが書いて下さったコードをもとに理解しながら書いていこうと思います。 こんかいの私のコードではなぜ配列に追加し、Cellに表示するとうことができなかったのでしょうか? 自分なりに考え、検索してみても理由が分かりませんでした。 たびたび申し訳ありませんがxg63ex2bさんの意見を聞きたいです。大まかな説明で結構です、お願いします
退会済みユーザー

退会済みユーザー

2022/07/29 06:40

コメントありがとうございます。 > こんかいの私のコードではなぜ配列に追加し、Cellに表示するとうことができなかったのでしょうか? hennsyuViewControllerのviewWillDisappearで配列に追加しているのに、画面上は追加されなかった理由ですね。 ```swift override func viewWillDisappear(_ animated: Bool) { if AppState.isEdited { let nikkiVC = storyboard?.instantiateViewController(withIdentifier: "nikkiTableViewController") as! nikkiTableViewController nikkiVC.nameArray.append(nameField.text!) nikkiVC.dateArray.append(nameField.text!) nikkiVC.hyoukaArray.append(hyoukaField.text!) nikkiVC.textViewArray.append(textField.text!) } } ``` > instantiateViewController(withIdentifier:) > Creates the view controller with the specified identifier and initializes it with the data from the storyboard. > (機械翻訳)指定された識別子を持つビューコントローラを作成し、ストーリーボードからのデータで初期化します。 > https://developer.apple.com/documentation/uikit/uistoryboard/1616214-instantiateviewcontroller nikkiTableViewControllerのインスタンスを毎回新たに生成しているからかなと思いました。 実際の画面に表示されているnikkiTableViewControllerの一覧(テーブル?)は、 hennsyuViewControllerのviewWillDisappearで生成したインスタンスとは別物ですので、 別物のインスタンスを操作しても画面上は何も変わらない、という状況になっていると思いました。 伝わりますでしょうか・・
coco7777

2022/08/01 08:35

回答ありがとうございます。  とても分かりやすい説明で理解できました!毎度毎度ありがとうございます instantiateViewController(withIdentifier:) を使わずに遷移できればインスタンスを毎回新たに生成しないので受け渡せる可能性もあるという認識で間違いないでしょうか? でも今回は可読性、利便性の面からコールバックを使った方が良いということですね
退会済みユーザー

退会済みユーザー

2022/08/01 14:57

コメントありがとうございます。 伝わったようで良かったです。 > instantiateViewController(withIdentifier:) を使わずに遷移できればインスタンスを毎回新たに生成しないので受け渡せる可能性もあるという認識で間違いないでしょうか? その認識でOKと思います。 > でも今回は可読性、利便性の面からコールバックを使った方が良いということですね そうですね、個人的にはそう思います。 nikkiTableViewControllerクラスのデータはnikkiTableViewControllerクラスが操作した方が良いと思いました。 --- 少しだけ本から引用してみました。 > 3.13 カプセル化 > データとロジックをグルーピング > 関連のあるデータとロジックをグルーピングして、1つのモジュールを定義します。関連性の強いデータ群とロジック群を、モジュールという膜で包み込むことを、カプセル化と呼んでいます。 > 異なるモジュールについては、互いに別物として、分離して扱います。 > プリンシプル オブ プログラミング P.84 > 4.2 結合度 > 相互依存モジュールは脆い > 結合が密なモジュールは、互いに依存してしまい、互いに影響してしまうので、様々な問題が生じます。 > 例えば、関連するモジュールの変更によって、結合しているモジュールに変更が必要になったり、動作に影響を与えたりします。 > また、モジュールを利用するには、そのモジュールが依存するモジュールも必要になるので、再利用しにくくなります。 > さらに、モジュールのコードが、単独では解読できないことになります。関連する複数のモジュールを読んだとしても、グローバル変数でつながっていたりすると、その動作を完全に把握するのは難しくなります。 > プリンシプル オブ プログラミング P.195
coco7777

2022/08/03 05:36

回答ありがとうございます! 引用の内容勉強になりました 相互依存し脆くなることを避けるためにも今回の場合、nikkiTableViewControllerクラスで操作する必要があるということですね。 最初に教えていただいたコードで実行したところcellが追加されました! 現在はcallbackで複数の値を配列に追加しcellに反映できるよう勉強しています。 なるべく自力で頑張りますができなかった場合また解説などお願いしたいです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問