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

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

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

RealmとはSQLiteやCore Dataに代わるモバイルデータベースです。iOSとAndroidの両方でサポートされています。

iOS

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

Swift

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

Q&A

解決済

1回答

1703閲覧

Realmで値の保存を遅らせたい

tarofess

総合スコア127

Realm

RealmとはSQLiteやCore Dataに代わるモバイルデータベースです。iOSとAndroidの両方でサポートされています。

iOS

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

Swift

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

0グッド

0クリップ

投稿2017/01/09 05:23

編集2017/01/10 22:55

現在以下の画面のようにtableviewのセルに3つtextfieldがあります。

screen説明

そして画面右上のOKが押されるとtextfieldの値がrealmに保存されるようにしていたのですが、コードを書いている時にtextfieldの編集が終わった時点でrealmに値が保存されることに気づきました。コードは以下のようになっています。

swift

1func textFieldShouldEndEditing(_ textField: UITextField) -> Bool { 2 let realm = try! Realm() 3 4 switch textField.tag { 5 case CellTextField.name.rawValue: 6 try! realm.write { 7 self.product?.name = textField.text 8 } 9 10 case CellTextField.category.rawValue: 11 try! realm.write { 12 self.product?.category = textField.text 13 } 14 15 case CellTextField.price.rawValue: 16 try! realm.write { 17 if !textField.text!.isEmpty { 18 self.product?.price.value = Int(textField.text!) 19 } 20 } 21 22 default: 23 break 24 } 25 return true 26 }

textfieldを編集しても画面左上のCencelが押されれば値は保存されないようにしたいので上記のコードではダメだと思いました。
なのでOKボタンのアクションのハンドラ内でrealmへの保存を行いたいのですが、realmでは値の保存を遅らせたりすることはできるのでしょうか?
その他例えばダミーのProductクラスを一つ作って、上記コードのtextFieldShouldEndEditingでそのダミーProductのインスタンスに値を入れつつ、OKが押された時にダミーのProductをrealmのProductに流しこもうかなと思ったのですが、手間がかかって面倒だと思いました......。
realmへの値の保存を遅らせるだけでなく、その他何かいい方法があれば教えていただきたいです。
よろしくお願いします。

///回答を受けての追記///

swift

1 let realm = try! Realm() 2 self.view.subviews.forEach({ view in 3 if let textField = view as? NameEditTableViewCell { 4 try! realm.write { 5 self.product?.name = textField.textLabel?.text 6 } 7 } 8 if let textField = view as? CategoryEditTableViewCell { 9 try! realm.write { 10 self.product?.name = textField.textLabel?.text 11 } 12 } 13 if let textField = view as? PriceEditTableViewCell { 14 try! realm.write { 15 self.product?.name = textField.textLabel?.text 16 } 17 } 18 })

///更なる追記///

1:

swift

1class NameEditTableViewCell: UITableViewCell { 2 3 @IBOutlet weak var nameTextField: UITextField! 4 5} 6 7class CategoryEditTableViewCell: UITableViewCell { 8 9 @IBOutlet weak var categoryTextField: UITextField! 10} 11 12class PriceEditTableViewCell: UITableViewCell { 13 14 @IBOutlet weak var priceTextField: UITextField! 15 16}

2: はい、viewcontrollerのフィールドにstoryboardのtableviewから引っ張ってきたtableviewのインスタンスがあります。

3:

swift

1func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 2 let type = self.displayCells()[indexPath.row] 3 let id = type.rawValue 4 let cell = self.tableView.dequeueReusableCell(withIdentifier: id, for: indexPath) 5 self.configureCell(targetCell: cell, type: type) 6 7 return cell 8 } 9 10func configureCell(targetCell: UITableViewCell, type: CellType) { 11 switch type { 12 case .name: 13 if let cell = targetCell as? NameEditTableViewCell { 14 cell.nameTextField.text = self.product?.name 15 cell.nameTextField.delegate = self 16 } 17 case .category: 18 if let cell = targetCell as? CategoryEditTableViewCell { 19 cell.categoryTextField.text = self.product?.category 20 cell.categoryTextField.delegate = self 21 } 22 case .price: 23 if let cell = targetCell as? PriceEditTableViewCell { 24 if let price = self.product?.price.value { 25 cell.priceTextField.text = String(describing: price) 26 } 27 cell.priceTextField.delegate = self 28 } 29 } 30 } 31

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

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

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

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

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

guest

回答1

0

ベストアンサー

textFieldShouldEndEditing(_:)デリゲートメソッドはキーボードの「改行」をタップした時に呼ばれるメソッドなので、たしかにこのコードでしたらrealmに3つのテキストフィールドの文字が保存されてしまいますね。
realmの問題よりも保存するタイミングの問題だと思います。
textFieldShouldEndEditing(_:)ではキーボードを閉じるだけにして、OKボタンのIBActionを設定してそこでテキストフィールドの文字をRealmで保存すればいいと思います。

追記:okActionメソッドを変更し、tableviewのvisibleCellsプロパティからcellを取得するようにしました。

//キーボードを閉じる func textFieldShouldEndEditing(_ textField: UITextField) -> Bool { //キーボードでEnterボタンを押したら、キーボードを閉じる textField.resignFirstResponder() return true }

OKボタンのIBActionを設定で各テキストフィールドの文字列をRealmに保存する。
Storyboard(またはXib)から以下のokAction(_:)メソッドに接続してください。

//ViewController.swift @IBAction func okAction(_ sender: Any) { //selfはViewControllerの想定。UITableviewの変数名をtableviewと想定。      //tableviewのvisibleCellsプロパティで今表示されているcellを全て取得できます。 self.tableview.visibleCells.forEach({ cell in if let cell = cell as? NameEditTableViewCell { //NameEditTableViewCellを取得する          try! realm.write { self.product?.name = cell.nameTextField.text//cellはNameEditTableViewCellにキャストされたので、nameTextFieldが取得できる } }        if let cell = cell as? CategoryEditTableViewCell { //CategoryEditTableViewCellを取得する          try! realm.write { self.product?.category = cell.categoryTextField.text } }        if let cell = cell as? PriceEditTableViewCell { //PriceEditTableViewCellを取得する          try! realm.write { self.product?.price.value = Int(textField.text!) } } }) /* //self.view.subviewsでViewControllerのサブビューを全て取得 self.view.subviews.forEach({ view in if let textField = view as? UITextField {//viewをUITextFieldにキャストする。こちら独自のUITextFieldのサブクラスを使用していましたらそちらに変えてください。 case CellTextField.name.rawValue: try! realm.write { self.product?.name = textField.text } case CellTextField.category.rawValue: try! realm.write { self.product?.category = textField.text } case CellTextField.price.rawValue: try! realm.write { if !textField.text!.isEmpty { self.product?.price.value = Int(textField.text!) } } default: break } } }) */ }

投稿2017/01/10 04:22

編集2017/01/11 01:53
SatoTakeshiX

総合スコア113

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

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

tarofess

2017/01/10 12:52

ご回答ありがとうございます。if let textField = view as? UITextFieldでキャストするクラスは複数あるので、少しご提示のコードを書き換えてみたのですが、うまく動きません。質問に追記しているのですが、self.view.subviews.forEach内のif let textField = view as? NameEditTableViewCellといった行でうまくキャストできていないようです。。。
SatoTakeshiX

2017/01/10 13:25

あーなるほど、よく見たらTableViewにカスタムのCellをそれぞれ作っていらっしゃるんですね。。 するとちょっと情報が足りないのでいろいろお聞きしたいです。 `okAction `メソッドはやりたいことは各CellのUITextFiledを取得してそのtextをrealmに保存することです。各CellのUITextFiledの取得ができていないので、取得するために、Viewの構造を知りたいです。以下の実装を教えていただけないでしょうか? (1と2が特に知りたいです。3は参考程度なイメージです!) --------- 1.NameEditTableViewCell、CategoryEditTableViewCell、PriceEditTableViewCellの実装 2.ViewControllerとUITableView関係(ViewControllerのプロパティでUITableView保持してます?) 3.`func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell `の実装
tarofess

2017/01/10 22:56

はい、それぞれのcellにカスタムcellを割り当てています。 質問に1と2と3について追記しました。 よろしくお願いします。
SatoTakeshiX

2017/01/11 01:38

回答を更新しました。UITableViewのvisibleCellsというプロパティで「今表示されているセル」が取得できるので、それをforEachで回して各セルをキャストしてUITextFieldを取得、realmに保存する処理に変更しています。ご確認ください
tarofess

2017/01/11 12:08

visibleCellsでtableviewのセルを取得できました!おかげで目的の動作が確認できて大変嬉しいです。最後まで丁寧に教えてくださり、誠にありがとうございましたmm
SatoTakeshiX

2017/01/11 12:10

良かったです!私も嬉しいです!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.51%

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

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

質問する

関連した質問