実現したいこと
現在、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 + 104 let height = estimateFrameForTextView(text: textView.text).height + 105 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 = self12 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 + 1017 let height = estimateFrameForTextView(text: textView.text).height + 1018 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 = true22 let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePanGesture(_:)))23 textView.addGestureRecognizer(panGesture)24 self.bgView.insertSubview(textView, belowSubview: self.dateLabel)25 }26 }
Swift
1// Model2import Foundation3import RealmSwift4 5class Model: Object {6 @objc dynamic var title: String = ""7 @objc dynamic var x: Double = 0.08 @objc dynamic var y: Double = 0.09 @objc dynamic var id: String = UUID().uuidString 10 override static func primaryKey() -> String? {11 return "id"12 }13}14
試したこと・調べたこと
上記の詳細・結果
元々textViewDidChange内でsave()を実行していたのですが、それだとtextViewの内容が変更される度に保存されてしまいました。(例えば、AAAと入力した時、"", "A", "AA", "AAA"が保存されてしまう)
update: .modifiedは、プライマリーキーを参照してCreateかUpdateを決めていると思うのですが、idをUUID().uuidStringというユニークなキーで保存してしまっているのが原因と考えています。しかし、どのように変更すれば良いか思いつかなかったので、ご教示いただけますと幸いです。
よろしくお願いいたします。
補足
特になし
0 コメント