gpt4 book ai didi

ios - 通过不同 View Controller 使用 Realm 时出现 RLMException

转载 作者:行者123 更新时间:2023-11-30 11:21:51 28 4
gpt4 key购买 nike

我正在 swift 中使用 Realm 创建一个要保存在用户设备上的喜爱产品列表。

简而言之,标签栏 Controller 中嵌入了 2 个 View Controller (A 和 B)。

  • View Controller A 显示从 Firebase 数据库获取的一些产品。
  • View Controller A 还有一个“添加到收藏夹”按钮,用于将产品添加到 Realm 实例。

  • View Controller B 嵌入一个表格 View 来显示此 Realm 实例的结果。

问题是,当我从 TableView 中删除一些产品时,我得到当我返回查看 Controller A 时,出现以下错误。

Terminating app due to uncaught exception 'RLMException', reason: 'Object has been deleted or invalidated

我了解到,当尝试从 Realm 访问已删除的对象或尝试重新添加之前删除的对象时,会发生此错误。这里的情况似乎并非如此。

感谢您的建议。

这是我的 View Controller A 中的“添加到收藏夹”按钮:

@IBAction func addToFavorites(_ sender: Any) {
let realm = try! Realm()
try! realm.write {
realm.add(currentProduct)
}
}

这是我的 View Controller B 中的 TableView 代码:

class ViewControllerB: UIViewController, UITableViewDataSource, UITableViewDelegate {


let realm = try! Realm()
var favorites: Results<Product>!

@IBOutlet weak var favoritesTableView: UITableView!

override func viewDidLoad() {
super.viewDidLoad()
favoritesTableView.delegate = self
favoritesTableView.dataSource = self
favoritesTableView.rowHeight = 70
}

override func viewWillAppear(_ animated: Bool) {
favorites = realm.objects(Product.self)
favoritesTableView.reloadData()
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return favorites.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! favoriteTableViewCell
let product = favorites[indexPath.row]
cell.productName.text = product.name
cell.productCategory.text = product.category
return cell
}

func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
let product = favorites[indexPath.row]
try! realm.write {
realm.delete(product)
}
tableView.deleteRows(at: [indexPath], with: UITableViewRowAnimation.bottom)
}
}

编辑:这是全 View Controller A

import UIKit
import RealmSwift

class ViewControllerA: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {

var products = [Product]()
var scannedProduct = Product()
var currentProduct = Product()
let realm = try! Realm()

@IBOutlet weak var myCollectionView: UICollectionView!
@IBAction func addToFavorites(_ sender: Any) {
try! realm.write {
realm.add(currentProduct)
}
}

override func viewDidLoad() {
super.viewDidLoad()

myCollectionView.delegate = self
myCollectionView.dataSource = self
myCollectionView.isPagingEnabled = true
myCollectionView.backgroundColor = UIColor.blue
layout()
}

override func viewDidAppear(_ animated: Bool) {
currentProduct = scannedProduct
}

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return products.count
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! collectionCell
cell.productName.text = products[indexPath.item].name
cell.codeLabel.text = products[indexPath.item].code
return cell
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: myCollectionView.bounds.width, height: myCollectionView.bounds.height)
}

func layout() {
if let flowLayout = myCollectionView.collectionViewLayout as? UICollectionViewFlowLayout {
flowLayout.scrollDirection = .horizontal
flowLayout.minimumLineSpacing = 0
}
}

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let currentVisibleCell = myCollectionView.visibleCells.first
let currentIndex = myCollectionView.indexPath(for: currentVisibleCell!)?.item
currentProduct = products[currentIndex!]
}
}

最佳答案

when trying to access deleted objects from Realm, That doesn't seem to be the case here.

其实...

    try! realm.write {
realm.delete(product)
}
tableView.deleteRows(at: [indexPath], with: UITableViewRowAnimation.bottom)

这两行不应该是这样的。你看,Realm 有一个叫做 NotificationToken 的东西,并且能够观察结果。根据示例,它应该如下所示:

var notificationToken: NotificationToken?

override func viewDidLoad() {
...
// Set results notification block
self.notificationToken = results.observe { (changes: RealmCollectionChange) in
switch changes {
case .initial:
// Results are now populated and can be accessed without blocking the UI
self.tableView.reloadData()
break
case .update(_, let deletions, let insertions, let modifications):
// Query results have changed, so apply them to the TableView
self.tableView.beginUpdates()
self.tableView.insertRows(at: insertions.map { IndexPath(row: $0, section: 0) }, with: .automatic)
self.tableView.deleteRows(at: deletions.map { IndexPath(row: $0, section: 0) }, with: .automatic)
self.tableView.reloadRows(at: modifications.map { IndexPath(row: $0, section: 0) }, with: .automatic)
self.tableView.endUpdates()
break
case .error(let err): // this is probably not relevant in a non-sync scenario
break
}
}

如果你有这个,那么理论上你可以删除自己的 tableView.deleteRows(at: [indexPath], with: UITableViewRowAnimation.bottom) 调用。每当发生更改(写入发生在 Realm 中)时,该观察者都会使 TableView 保持最新状态。

关于ios - 通过不同 View Controller 使用 Realm 时出现 RLMException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51180711/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com