Swift UIKit中删除Realm对象后报错‘Object has been deleted or invalidated.’
问题描述
我想实现的功能:把照片保存到Realm,并用Results<PhotoModel.self>数组在TableView中展示这些照片。
应用整体逻辑:这是一个Unsplash API客户端,MainVC通过CollectionView展示照片,点击任意照片可进入DetailedVC,在这个页面可以标记照片为收藏;收藏的照片可以通过TabBar进入FavoriteVC,在TableView中查看。
遇到的问题:在DetailedVC点击按钮保存照片正常,删除也正常,但再次点击保存按钮,或者从MainVC打开同一张照片时应用崩溃。
我觉得自己没在删除后访问Realm对象,因为我操作的是从JSON获取并存在本地变量里的数据,不是Realm数据库里的对象。
我用的保存/删除方法如下:
@objc func addToFavorite() { guard let photoObject = photoObject else { return } if realm.objects(PhotoModel.self).contains(where: { $0.id == photoObject.id }) { deleteFromDB(photoObject) } else { saveToDB(photoObject) } }
问题修复方案
核心问题分析
崩溃大概率是因为你在删除操作时直接使用了本地的photoObject——如果这个对象之前已经被保存到Realm,删除后它会被标记为已失效(invalidated),后续再对这个失效对象进行操作(比如再次保存),或者从其他页面传递这个失效对象时,就会触发Realm的异常崩溃。
修复步骤
- 修改收藏/取消收藏逻辑
把原来直接用本地对象判断和删除的逻辑,改成先从Realm中查询对应ID的对象,再进行操作:
@objc func addToFavorite() { guard let photoId = photoObject?.id else { return } // 先从Realm查询对应ID的对象 if let existingPhoto = realm.objects(PhotoModel.self).first(where: { $0.id == photoId }) { // 删除Realm中查到的有效对象 deleteFromDB(existingPhoto) } else { // 保存本地对象到Realm saveToDB(photoObject!) } }
- 确保删除方法操作有效对象
检查你的deleteFromDB方法,必须在Realm事务中删除查询到的对象,而不是本地的失效对象:
func deleteFromDB(_ photo: PhotoModel) { do { try realm.write { realm.delete(photo) } // 这里可以更新按钮状态,比如切换成"收藏"按钮 } catch { print("删除照片失败:\(error.localizedDescription)") } }
- 避免传递Realm对象
从MainVC跳转到DetailedVC时,不要直接传递Realm对象,而是传递照片的id。在DetailedVC中,根据id要么从Unsplash API重新拉取数据,要么从Realm查询(如果已收藏),这样就不会持有失效的Realm对象引用,彻底避免崩溃。
额外注意点
- 崩溃时可以查看Xcode的崩溃日志,如果提示
Attempt to access an invalidated object,就确认是失效对象引用的问题,按上面的方案修复即可。 - Realm的
Results是实时更新的,FavoriteVC的TableView会自动同步数据,不用手动刷新,确保你的TableView数据源直接绑定Results即可。
内容的提问来源于stack exchange,提问作者Vladislav Katsubo
相关产品推荐
相关产品推荐

