実現したいこと
現在、Realmを用いてUITextViewに入力された文字列およびtextViewの座標の保存を行なっています。
実際にあるアプリの機能で例えると、Instagramの投稿をする時のような感じです。
例えばストーリーに写真をアップする際に文字列を写真の上に載せたい場合、
ユーザーがテキストを表示→入力→画面上の適当な部分をタップして文字列の編集終了→文字列をドラッグして好きな場所に文字を置く
というような流れがあります。この一連の流れの実現はできたのですが、これをRealmで保存する際に少々手こずってしまっています。ユーザーは自由にtextViewの内容を編集したり、textViewの位置を変更することができます。変更した後の状態をRealmで保存したいです。Realmに保存される内容は文字列、x座標, y座標です。
発生している問題・分からないこと
RealmのUpdateは、
Swift
1update: .modified
とすれば良いと思っていたのですが、これだと普通の保存になってしまいます。例えば、ドラッグ&ドロップで元々のTextViewの位置を移動させた時、ユーザーが移動させる前と後の両方の状態が残ってしまっています。
該当のソースコード
Swift
1// 保存の関数 2func save(text: String, x: Double, y: Double) { 3 let realm = try! Realm() 4 let model = Model() 5 model.title = text 6 model.x = x 7 model.y = y 8 try! realm.write { 9 realm.add(model, update: .modified) 10 } 11 }
Swift
1// PanGesture(ユーザーがドラッグ&ドロップをさせた時) 2@objc func handlePanGesture(_ recognizer: UIPanGestureRecognizer) { 3 guard let textView = recognizer.view as? UITextView else { return } 4 let translation = recognizer.translation(in: textView.superview) 5 var newX = textView.center.x + translation.x 6 var newY = textView.center.y + translation.y 7 8 newX = min(max(newX, textView.frame.width / 2 + 10), bgView.frame.width - textView.frame.width / 2 - 10) 9 newY = min(max(newY, textView.frame.height / 2 + 10), bgView.frame.height - textView.frame.height / 2 - 10) 10 11 textView.center = CGPoint(x: newX, y: newY) 12 recognizer.setTranslation(.zero, in: textView.superview) 13 if recognizer.state == .ended { 14 save(text: textView.text, x: newX, y: newY) 15 } 16 }
Swift
1// TextViewの内容が変更された時 2func textViewDidChange(_ textView: UITextView) { 3 let width = estimateFrameForTextView(text: textView.text).width + 10 4 let height = estimateFrameForTextView(text: textView.text).height + 10 5 textView.frame.size = CGSize(width: width, height: height) 6 UserDefaults.standard.set(textView.text, forKey: "text") 7 UserDefaults.standard.set(textView.center.x, forKey: "x") 8 UserDefaults.standard.set(textView.center.y, forKey: "y") 9 } 10 11override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { 12 let text = UserDefaults.standard.string(forKey: "text") ?? "" 13 let x = UserDefaults.standard.double(forKey: "x") 14 let y = UserDefaults.standard.double(forKey: "y") 15 print(text, x, y) 16 save(text: text, x: x, y: y) 17 self.view.endEditing(true) 18 }
Swift
1//読み込み(Realmの内容を読み込んで、保存されている数に合わせてtextViewを生成。それぞれのtextViewを保存されている座標の位置に設定し、内容を反映させる。) 2override func viewWillAppear(_ animated: Bool) { 3 super.viewWillAppear(animated) 4 5 let realm = try! Realm() 6 self.itemList = realm.objects(Model.self).filter("date == %@", dateLabel.text!) // 今日の分の内容だけ表示させるようにfilterをかける。 7 print(itemList!) 8 9 for i in 0..<itemList.count { 10 let textView = UITextView() 11 textView.delegate = self 12 textView.text = itemList[i].title 13 textView.frame = CGRect(x: itemList[i].x, y: itemList[i].y, width: 100, height: 44) 14 textView.textColor = .black 15 textView.font = UIFont.systemFont(ofSize: 20) 16 let width = estimateFrameForTextView(text: textView.text).width + 10 17 let height = estimateFrameForTextView(text: textView.text).height + 10 18 textView.frame.size = CGSize(width: width, height: height) 19 textView.backgroundColor = UIColor(red: 255/255, green: 255/255, blue: 255/255, alpha: 0.8) 20 textView.textAlignment = .center 21 textView.isEditable = true 22 let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePanGesture(_:))) 23 textView.addGestureRecognizer(panGesture) 24 self.bgView.insertSubview(textView, belowSubview: self.dateLabel) 25 } 26 }
Swift
1// Model 2import Foundation 3import RealmSwift 4 5class Model: Object { 6 @objc dynamic var title: String = "" 7 @objc dynamic var x: Double = 0.0 8 @objc dynamic var y: Double = 0.0 9 @objc dynamic var id: String = UUID().uuidString 10 override static func primaryKey() -> String? { 11 return "id" 12 } 13} 14
試したこと・調べたこと
- teratailやGoogle等で検索した
- ソースコードを自分なりに変更した
- 知人に聞いた
- その他
上記の詳細・結果
元々textViewDidChange内でsave()を実行していたのですが、それだとtextViewの内容が変更される度に保存されてしまいました。(例えば、AAAと入力した時、"", "A", "AA", "AAA"が保存されてしまう)
update: .modifiedは、プライマリーキーを参照してCreateかUpdateを決めていると思うのですが、idをUUID().uuidStringというユニークなキーで保存してしまっているのが原因と考えています。しかし、どのように変更すれば良いか思いつかなかったので、ご教示いただけますと幸いです。
よろしくお願いいたします。
補足
特になし
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2024/03/22 05:44