現状
registeredMoviesに他のViewControllerでrealm.writeで保存された
Realmから取り出した全てのデータがあり、
テーブルに表示するデータであるdataSourceという二つの変数を用意しました。
updateRegisteredMovieというメソッドでRealmに保存したid:Intで
データ(インデックス)を識別して、isWatedがtrueかfalseかによって
segmentedControllのcase0かcase1にデータを表示しているか判断しています。
疑問
UISwipeactionでupdateRegisteredMovieをshareActionでdeleteRegisteredMovieを
deleteActionで行いたいです。
updateRegisteredMovieの方は他の方から教わりこの方法でデータの更新できるのですが、
deleteRegisteredMovieの方は自分で書いてみたのですが、このまま実行すると
Object has been deleted or invalidated
とエラーが出てしまいます。
Realmで一つのCellを削除する場合どのように行えば良いですか?
補足
cellをスワイプしたときにShare,deleteを表示するところまでは出来ています。
let selectedRegisterdMovieID = self.dataSorce[indexPath.row].id
はTableViewのindexとRealmのindexのデータの個数が違う場合に更新対象と違うデータがとれてしまう可能性を防ぐために
Realmに保存したidで削除/更新するindexを判断しています。
ソースコード
import UIKit import RealmSwift class ListViewController: UIViewController { @IBOutlet weak var table:UITableView! @IBOutlet weak var segmentedControl:UISegmentedControl! private var registeredMovies = [RegisteredMovie]() private var dataSorce: [RegisteredMovie] { switch segmentedControl.selectedSegmentIndex { case 0: return registeredMovies.filter { !$0.isWatched} case 1: return registeredMovies.filter { $0.isWatched} default: fatalError("Unknown case.") } } override func viewDidLoad() { super.viewDidLoad() self.setupTable() } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) loadRegisteredMovies() } @IBAction func segmentSelected(_ sender: UISegmentedControl) { table.reloadData() } } extension ListViewController { private func setupTable() { table.delegate = self table.dataSource = self table.register(ListTableViewCell.nib(), forCellReuseIdentifier: ListTableViewCell.identifier) } } extension ListViewController { private func loadRegisteredMovies() { do { let realm = try Realm() let storedRegisteredMovies = Array(realm.objects(RegisteredMovie.self)) registeredMovies = storedRegisteredMovies table.reloadData() } catch { print(error) } } private func updateRegisteredMovie(of id: Int, isWatched: Bool) { guard let index = registeredMovies.firstIndex(where: { $0.id == id }) else { return } do { let realm = try Realm() try realm.write { registeredMovies[index].isWatched = isWatched } table.reloadData() } catch { print(error) } } //データを削除するメソッド func deleteRegisteredMovie(of id: Int) { guard let index = registeredMovies.firstIndex(where: { $0.id == id }) else { return } do { let realm = try Realm() try realm.write { realm.delete(registeredMovies[index]) } self.table.reloadData() } catch { print(error) } } //swipe action func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? { // シェアのアクションを設定する let shareAction = UIContextualAction(style: .normal , title: "完了") { (ctxAction, view, completionHandler) in //データをcase1に更新 let selectedRegisterdMovieID = self.dataSorce[indexPath.row].id let isWatched = self.segmentedControl.selectedSegmentIndex == 0 self.updateRegisteredMovie(of: selectedRegisterdMovieID, isWatched: isWatched) completionHandler(true) self.table.reloadData() } // シェアボタンのデザインを設定する let shareImage = UIImage(systemName: "arrowshape.turn.up.right.fill")?.withTintColor(UIColor.white, renderingMode: .alwaysTemplate) shareAction.image = shareImage shareAction.backgroundColor = UIColor(red: 0/255, green: 125/255, blue: 255/255, alpha: 1) // 削除のアクションを設定する let deleteAction = UIContextualAction(style: .destructive, title:"削除") { (ctxAction, view, completionHandler) in //疑問点 let selectedDeleteMovieID = self.dataSorce[indexPath.row].id self.deleteRegisteredMovie(of: selectedDeleteMovieID) tableView.deleteRows(at: [indexPath], with: .automatic) completionHandler(true) } // スワイプでの削除を無効化して設定する let swipeAction = UISwipeActionsConfiguration(actions:[deleteAction, shareAction]) swipeAction.performsFirstActionWithFullSwipe = false return swipeAction } } extension ListViewController: UITableViewDataSource { --以下省略
Realmのクラスには以下が含まれています。
import Foundation import RealmSwift class RegisteredMovie: Object { @objc dynamic var id: Int = 0 @objc dynamic var title: String = "" @objc dynamic var release_date: String = "" @objc dynamic var poster_path: String = "" @objc dynamic var isWatched: Bool = false }
回答1件
あなたの回答
tips
プレビュー