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

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

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

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Swift

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

Q&A

2回答

1203閲覧

【Swift】カスタムセル内のUITextFieldの値を取得する方法

duck015

総合スコア29

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Swift

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

0グッド

1クリップ

投稿2020/03/16 06:30

編集2020/03/16 06:34

前提・実現したいこと

SwiftでToDoアプリを作成しています。
「Done」ボタンをタップしたら(関数doneButtonTapped())各セルに表示されているデータをUserDefaultsに保存したいです。
(今回の場合、「パンを買う」「買い物」「3月16日」という文字列を保存したいです)

一番上のセルはTaskTitleTableViewCellというカスタムセルになっており、UITextFieldを設置しています。
現在、そのセルに設置したUITextFieldの値を取得する方法が分からずいます(2,3番目の値は取得できています)。

試しにセルのインスタンスを作成し、下記の通り試してみましたがnilとなり、エラーが発生してしまいます。
解決策としては、セルのUITextFieldの変化を監視し、何らかの方法でAddTaskViewControllerに通知をできればよいと考えているのですが、具体的にどのように実装すれば良いか見当がついておりません。
そこで、初歩的な質問で恐縮ですが、アドバイスいただけないでしょうか?

let cell = TaskTitleTableViewCell()    print(cell.taskTitleTextField.text ?? "nil") //Fatal error: Unexpectedly found nil while unwrapping an Optional value

イメージ説明

該当のソースコード

AddTaskViewController

1class AddTaskViewController: UIViewController { 2 3 @IBOutlet weak var largeTitleBackgroundView: UIView! 4 @IBOutlet weak var addTaskTableView: UITableView! 5 6 let titleLabelArray = ["", "カテゴリ", "日付"] 7 8 var detailLabelArray: [String] = ["", "個人", ""] 9 10 let datePicker = UIDatePicker() 11 12 let datePickerView = UIView() 13 14 override func viewDidLoad() { 15 super.viewDidLoad() 16 largeTitleBackgroundView.layer.addShadow() 17 initializeTableView() 18 detailLabelArray[2] = getToday() 19 } 20 21 override func viewWillAppear(_ animated: Bool) { 22 super.viewWillAppear(true) 23 addTaskTableView.reloadData() 24 } 25 26 private func getToday(format: String = "M月dd日") -> String { 27 let now = Date() 28 let formatter = DateFormatter() 29 formatter.dateFormat = format 30 return formatter.string(from: now) 31 } 32 33 private func initializeTableView() { 34 addTaskTableView.delegate = self 35 addTaskTableView.dataSource = self 36 addTaskTableView.backgroundColor = UIColor(red: 250, green: 250, blue: 250, alpha: 1.0) 37 addTaskTableView.register(UINib(nibName: "TaskTitleTableViewCell", bundle: nil), forCellReuseIdentifier: "TaskTitleTableViewCell") 38 } 39 40 @objc private func doneBarButtonTapped() -> String { 41 let formatter = DateFormatter() 42 formatter.dateFormat = "M月dd日" 43 detailLabelArray[2] = formatter.string(from: datePicker.date) 44 addTaskTableView.reloadData() 45 datePickerView.removeFromSuperview() 46 return formatter.string(from: datePicker.date) 47 } 48 49 private func showDatePicker() { 50 datePicker.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: datePicker.bounds.size.height) 51 datePicker.datePickerMode = UIDatePicker.Mode.date 52 datePicker.timeZone = NSTimeZone.local 53 datePicker.locale = NSLocale(localeIdentifier: "ja_JP") as Locale 54 datePickerView.frame = datePicker.bounds 55 let toolbar = UIToolbar() 56 let spaceItem = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil) 57 let doneItem = UIBarButtonItem(title: "完了", style: .plain, target: self, action: #selector(doneBarButtonTapped)) 58 toolbar.setItems([spaceItem, doneItem], animated: true) 59 toolbar.sizeToFit() 60 datePickerView.addSubview(datePicker) 61 datePickerView.addSubview(toolbar) 62 view.addSubview(datePickerView) 63 let screenSize = UIScreen.main.bounds.size 64 datePickerView.frame.origin.y = screenSize.height 65 UIView.animate(withDuration: 0.3) { 66 self.datePickerView.frame.origin.y = screenSize.height - self.datePickerView.bounds.size.height 67 } 68 } 69 70 @IBAction func doneButtonTapped(_ sender: Any) { 71 print(detailLabelArray[1]) 72 print(detailLabelArray[2]) 73 let cell = TaskTitleTableViewCell() 74 print(cell.taskTitleTextField.text ?? "nil") 75 } 76 77 @IBAction func cancelButtonTapped(_ sender: Any) { 78 self.navigationController?.popViewController(animated: true) 79 } 80 81} 82 83extension AddTaskViewController: UITableViewDelegate, UITableViewDataSource { 84 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 85 return 3 86 } 87 88 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 89 let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "addCell", for: indexPath) 90 let taskTitleCell = addTaskTableView.dequeueReusableCell(withIdentifier: "TaskTitleTableViewCell", for: indexPath) as! TaskTitleTableViewCell 91 if indexPath.section == 0 && indexPath.row == 0 { 92 print(taskTitleCell.taskTitleTextField.text ?? "aa") 93 return taskTitleCell 94 } 95 cell.textLabel?.text = titleLabelArray[indexPath.row] 96 cell.detailTextLabel?.text = detailLabelArray[indexPath.row] 97 return cell 98 } 99 100 func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { 101 return CGFloat.leastNormalMagnitude 102 } 103 104 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 105 addTaskTableView.deselectRow(at: indexPath, animated: true) 106 switch indexPath.row { 107 case 0: 108 return 109 case 1: 110 self.performSegue(withIdentifier: "toCategoryList", sender: nil) 111 case 2: 112 showDatePicker() 113 default: 114 return 115 } 116 } 117}

TaskTitleTableViewCell

1class TaskTitleTableViewCell: UITableViewCell, UITextFieldDelegate { 2 3 @IBOutlet weak var taskTitleTextField: UITextField! 4 5 override func awakeFromNib() { 6 super.awakeFromNib() 7 taskTitleTextField.delegate = self 8 } 9 10 override func setSelected(_ selected: Bool, animated: Bool) { 11 super.setSelected(selected, animated: animated) 12 } 13 14 func textFieldShouldReturn(_ textField: UITextField) -> Bool { 15 textField.resignFirstResponder() 16 return true 17 } 18}

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

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

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

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

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

guest

回答2

0

試しにセルのインスタンスを作成し、下記の通り試してみましたがnilとなり、エラーが発生してしまいます。

新しいインスタンスと、画面に表示されているインスタンスは別物なので、そりゃそうです。

良い方法かどうかは微妙ですが、

https://developer.apple.com/documentation/uikit/uitableview/1614983-cellforrow
cellForRow(at:)

という関数で指定したIndexPathのセルのインスタンスが取れますので(ちゃんとnilチェックはしてください)、TaskTitleTableViewCell型にキャストしてからtaskTitleTextFieldにアクセスしてみてくてださい。

投稿2020/03/16 07:39

takabosoft

総合スコア8356

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

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

0

下記リンクでは、UITableViewに表示するデータをメンバ変数として持っています。
同じように、TaskTitleTableViewCellに表示するデータをインスタンスのメンバ変数として持っておけばいいだけかと思います。

UITableViewはセルにUITableViewCellを表示しているだけ

投稿2020/03/16 11:40

freemann

総合スコア264

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

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

takabosoft

2020/03/17 00:13

そのリンク先のコードは、セルのリサイクルの機構が入っていないので、あまり良いサンプルではないですね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問