Realm object has been deleted or invalidated

后端 未结 12 1103
粉色の甜心
粉色の甜心 2020-12-13 08:20

When I start my app, I perform an API call to see whether there\'s new data available. The data is stored in my local Realm database, and some of it is displayed in the init

相关标签:
12条回答
  • 2020-12-13 08:45

    after spent a day, i figure out with the remove DispatchQueue.main.async in my realm.delete() function and finally it worked.

    DispatchQueue.main.async {
      realm.delete()
    }
    

    to

    realm.delete()
    
    0 讨论(0)
  • 2020-12-13 08:50

    Try to create the element on realm instead of add

    So:

    try! realm.write {
            realm.add(...)
        }
    

    Replace with:

    try! realm.write {
            realm.create(...)
        }
    

    And then after the delete operation realm should work as expected!

    0 讨论(0)
  • 2020-12-13 08:52

    In my case I was deleting data from 2 tables at once.. one with a foreign to the other.

            let itemToDelete = counters[indexPath.row]
            let realm = try! Realm()
            try! realm.write {
                realm.delete(itemToDelete)
                let predicate = NSPredicate(format: "counterid = \(c.id)")
                let children = realm.objects(Details.self).filter(predicate)
                realm.delete(children)
            }
    

    But the problem was that I was trying to delete the children of the item that does not exist anymore. Switching the order, solved it!

            let itemToDelete = counters[indexPath.row]
            let realm = try! Realm()
            try! realm.write {
                let predicate = NSPredicate(format: "counterid = \(c.id)")
                let children = realm.objects(Details.self).filter(predicate)
                realm.delete(children)
                realm.delete(itemToDelete) //this should be deleted after
            }
    

    Hope this helps someone else!

    0 讨论(0)
  • 2020-12-13 08:52

    What you can do is observe the Results<> object returned from your initial Realm query (the one used to populate your list/table view) and update that list in the observer callback method whenever there is a change in the database.

    Just make sure that you use the same Realm instance to delete/modify the object as the one used for the initial query.

    EDIT:

    Some code examples:

    let realm = Realm()
    let results = realm.objects(Favourite.self)
    let notificationToken = results.observe { [weak self] (changes) in
        guard let tableView = self?.tableView else { return }
        tableView.reloadData()
    }
    
    // Somewhere else
    try? realm.write {
        if let favourite = results.first {
             realm.delete(favourite)
        }
    }
    
    // OR
    if let objectRealm = results.first?.realm {
        try? objectRealm.write {
            objectRealm.delete(results.first!)
        }
    }
    
    // Don't forget to stop observing in deinit{}
    // notificationToken.invalidate()
    
    0 讨论(0)
  • 2020-12-13 08:55

    The issue was in my FavoritesHelper class. It had both a favoriteLeagueIDs and favoriteLeagues property. I always set both of them and used the IDs for internal usage and the other property for whenever I want some data from these leagues.

    This meant, that all favorite leagues were constantly referenced by the favoriteLeagues property (of the type [League]), thus crashing the app when I wanted to fetch them after they're invalidated.

    What I've done to fix this, was to change the property favoriteLeagues to a computed property as follows:

    var favoriteLeagues: [League] {
        get {
            var leagues = [League]()
            for id in favoriteLeagueIDs {
                if let league = realm.objectForPrimaryKey(League.self, key: id) {
                    leagues.append(league)
                }
            }
            return leagues
        }
    }
    

    Now the leagues are no longer referenced and just get loaded from the database when I need to read them. Invalidated or deleted objects don't get loaded because of the if let statement (the Realm.objectForPrimaryKey(:key:) method returns nil in such a case).

    0 讨论(0)
  • 2020-12-13 08:55

    you can calling isInvalidated or invalidated to judge the object is invalid (YES) or not (NO). you can also write a a custom method to define what is real invalidate

    look for the document ,we will see a property:

     /**
     Indicates if the object can no longer be accessed because it is now invalid.
    
     An object can no longer be accessed if the object has been deleted from the Realm that manages it, or
     if `invalidate` is called on that Realm.
     */
    @property (nonatomic, readonly, getter = isInvalidated) BOOL invalidated;
    

    the invalidated is readonly but what does isInvalidated mean?

    it is equals to - (BOOL)invalidated { return invalidated; }

    it means that you can write a a custom method to define what is real invalidate you want.

    0 讨论(0)
提交回复
热议问题