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

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

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

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

Swift

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

Q&A

解決済

1回答

1724閲覧

セルの中のテキストフィールドの値を変数に格納したい

emilio

総合スコア15

Xcode

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

Swift

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

0グッド

0クリップ

投稿2020/02/21 10:03

編集2020/02/22 01:36

前提・実現したいこと

xcodeでアプリを作っています。TableViewCellの中にTextFieldを配置して入力された値を取得したいのですが、エラーが出てしまいうまくいきません。
テキストフィールドに数字を入力して次のテキストフィールドをタップするとクラッシュします。

発生している問題・エラーメッセージ

testapp3[3948:200218] -[testapp3.EditView4Controller TextField:]: unrecognized selector sent to instance 0x7f9957d14c20 -[testapp3.EditView4Controller TextField:]: unrecognized selector sent to instance 0x7f9957d14c20 (null)

該当のソースコード(swift)

EditView4Controller.swift

1 2 3import UIKit 4 5 6struct Info_k: Codable { 7 var Item: String 8 var number: Int 9} 10 11class EditView4Controller: UIViewController, UITableViewDataSource, UITableViewDelegate, InputTextTableCellDelegate { 12 13 var tag: Int = 0 14 var cellIdentifier: String = "" 15 let storemanager = StoreManager() 16 var Items = [Info_k]() 17 18 @IBOutlet weak var tableView0: UITableView! 19 @IBOutlet weak var tableView1: UITableView! 20 @IBOutlet weak var button_save: UIButton! 21 22 23 24 override func viewDidLoad() { 25 super.viewDidLoad() 26 Items = storemanager.load(key: "Items") 27 print(Items) 28 } 29 30 override func didReceiveMemoryWarning() { 31 super.didReceiveMemoryWarning() 32 } 33 34 func ChecktableView(_ tableView: UITableView) -> Void { 35 if(tableView.tag == 0) { 36 tag = 0 37 cellIdentifier = "InputTextCell0" 38 } else { 39 tag = 1 40 cellIdentifier = "InputTextCell1" 41 } 42 } 43 44 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 45 return Items.count 46 } 47 48 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { ChecktableView(tableView) 49 50 let cell: InputTextTableCell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath ) as! InputTextTableCell 51 if tableView.tag == 0 { 52 cell.textLabel!.text = Items[indexPath.row].Item 53 } else { 54 cell.delegate = self 55 56 } 57 return cell 58 } 59 60 func tableView(tableView: UITableView, heightForRowAtIndexPath idexPath: NSIndexPath) -> CGFloat { 61 return InputTextTableCell.height() 62 } 63 64 65 66 func textFieldDidEndEditing(cell: InputTextTableCell, value: NSString) -> () { 67 68 69 let path = tableView1.indexPathForRow(at: cell.convert(cell.bounds.origin, to: tableView1)) 70 print(path!.row) 71 72 NSLog("row = %d, value = %@", path!.row, value) 73 74 } 75 76 77 78 @IBAction func button_save(_ sender: Any) { 79 80 storemanager.save(value: Items, key: "Items") 81 } 82} 83

InputTextTableCell.swift

1 2 3import UIKit 4 5protocol InputTextTableCellDelegate { 6 func textFieldDidEndEditing(cell: InputTextTableCell, value: NSString) -> () 7} 8 9class InputTextTableCell: UITableViewCell, UITextFieldDelegate { 10 11 12 13 var delegate: InputTextTableCellDelegate! = nil 14 15 override func awakeFromNib() { 16 super.awakeFromNib() 17 } 18 19 override func setSelected(_ selected: Bool, animated: Bool) { 20 super.setSelected(selected, animated: animated) 21 22 } 23 static func height() -> CGFloat { 24 return 75.0 25 } 26 27 internal func textFieldShouldReturn(textField: UITextField) -> Bool { 28 textField.resignFirstResponder() 29 return true 30 } 31 32 internal func textFielddidEndEiting(textField: UITextField) { 33 self.delegate.textFieldDidEndEditing(cell: self, value: textField.text! as NSString) 34 } 35} 36

Storyboardはこんな感じです。↓

イメージ説明

試したこと

TextFielddidEndEditingの関数がおかしいのかと思い中身を消してみましたがうまくいきませんでした。

補足情報(FW/ツールのバージョンなど)

macOS Catalina 10.15.3
xcode 11.3.1

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

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

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

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

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

hoshi-takanori

2020/02/21 10:45

EditView4Controller に対して TextField: というメソッドが呼ばれているようですが、Storyboard のどこかで設定されているのでしょうか?
emilio

2020/02/21 15:12

ソースコードのどこの部分でしょうか? TextFieldはTableViewCell内に配置しています。
hoshi-takanori

2020/02/21 20:03

[testapp3.EditView4Controller TextField:]: unrecognized selector sent というエラーが出そうな箇所が質問文中には見当たらなかったので、ストーリーボードを疑ってます。
emilio

2020/02/22 01:41

Storyboardの画像を追加しました。よろしくお願いします。 TextFieldはSent Events 項のEditingDidEndとのみ接続を持っています。ClassはUITextFieldです。
guest

回答1

0

ベストアンサー

Storyboard を再現してみました。この UITextField に何か変なアクションが接続されてるような気がするので、ご確認ください。(あくまで勘なので、違ったらごめんなさい。)

イメージ説明


ところで、ソースを拝見して、いくつか気になることがあるので指摘させていただきます。

まず、テーブルが横に二つ並んでますが、これらは独立してスクロールするので、項目数が多くなったときにスクロールすると名前と個数の対応が合わなくなってしまうと思います。一つにまとめた方がいいのではないでしょうか。

また、デリゲートのメソッド名ですが、

swift

1class EditView4Controller: UIViewController, UITableViewDataSource, UITableViewDelegate, InputTextTableCellDelegate { 2 3 func tableView(tableView: UITableView, heightForRowAtIndexPath idexPath: NSIndexPath) -> CGFloat { 4 return InputTextTableCell.height() 5 } 6 7}

swift

1class InputTextTableCell: UITableViewCell, UITextFieldDelegate { 2 3 internal func textFieldShouldReturn(textField: UITextField) -> Bool { 4 textField.resignFirstResponder() 5 return true 6 } 7 8 internal func textFielddidEndEiting(textField: UITextField) { 9 self.delegate.textFieldDidEndEditing(cell: self, value: textField.text! as NSString) 10 } 11}

これらのメソッドの宣言部分で警告が出ていると思いますが、これは最初の引数(tableView や textField)の前に _ が抜けてるためです。この _引数ラベルの省略 というやつで、これがあるとないとでは異なるメソッドという扱いになり、これらのメソッドは呼ばれてないと思いますのでご注意ください。


タイトルにもある「セルの中のテキストフィールドの値を変数に格納」する方法ですが、保存ボタンが押されたときにまとめて保存したいってことですよね? 保存ボタンが押されたタイミングで各セルの中のテキストフィールドの値を取得しようとお考えでしょうが、TableView のセルは必要に応じて作られるものなので、スクロールすると画面に表示されてないものは消えてしまいます。ので、入力されたデータは別途保存しておく必要があります。

まず、入力された個数を入れる配列を用意します。

swift

1class EditView4Controller: UIViewController, UITableViewDataSource, UITableViewDelegate, InputTextTableCellDelegate { 2 3 var numbers = [Int]()

次に、Items の各要素から number を取り出して numbers に格納します。

swift

1 override func viewDidLoad() { 2 super.viewDidLoad() 3 Items = storemanager.load(key: "Items") 4 print(Items) 5 6 numbers = Items.map { $0.number } 7 print(numbers) 8 }

個数の表示には Items の各要素の number の代わりに、numbers を使います。
(InputTextTableCell に @IBOutlet weak var textField: UITextField! が必要です。)

swift

1 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { ChecktableView(tableView) 2 3 let cell: InputTextTableCell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath ) as! InputTextTableCell 4 if tableView.tag == 0 { 5 cell.textLabel!.text = Items[indexPath.row].Item 6 } else { 7 cell.delegate = self 8 cell.textField.text = String(numbers[indexPath.row]) 9 } 10 return cell 11 }

また、入力時にはテキストフィールドから値を取得して numbers に保存しておきます。
(textFieldDidEndEditing だとフォーカスが外れた時しか呼ばれないので、編集してそのままボタンを押すと古い値のままで button_save が呼ばれます。これを防ぐには UITextFieldの変更通知を受け取る方法 をどうぞ。)

swift

1 func textFieldDidEndEditing(cell: InputTextTableCell, value: NSString) -> () { 2 let path = tableView1.indexPathForRow(at: cell.convert(cell.bounds.origin, to: tableView1)) 3 print(path!.row) 4 5 if let text = cell.textField.text, 6 let number = Int(text) { 7 numbers[path!.row] = number 8 print(number) 9 } 10 }

あとは button_save で Items の各要素の number に numbers の値をセットすればいいと思います。
(たぶん Realm を使ってると思いますが、私は Realm を知らないので、あとはお任せします。)

投稿2020/02/22 04:16

編集2020/02/22 07:33
hoshi-takanori

総合スコア7895

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

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

emilio

2020/02/22 06:39

SetEvents の接続を切ったらうまくいくようになりました!ありがとうございました!! また、アドバイスありがとうございます。一つのtableViewにまとめてみようと思います。 あと、テキストフィールドに入力された値を変数に格納したいのですがどのようにすれば良いかわかりますか?tableView内のTextFieldへのアクセスの仕方がわからず苦戦していますので可能なら教えていただきたいです。
hoshi-takanori

2020/02/23 00:50

書き忘れてましたが、InputTextTableCell の delegate は weak にしないと循環参照が起こる可能性があります。その際、protocol InputTextTableCellDelegate: AnyObject { ... } とする必要があります。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問