Procedure when object is invalidated

Sorry my ignorance but i have to ask because i’ve been looking around for sometime and I don’t think theres a clear answer on this.

An invalidated object crash is… according to stackoverflow

The Object has been deleted or invalidated error will occur if an object has been deleted from a Realm, but you subsequently try and access a stored property of an instance of that object that your code was hanging onto since before the deletion."

thats ok… although i dont yet quite understand why the object persists in the queries results.

But imagine the current situation. I’ve deleted an object. The object persists in the result queries, now im forced to verify its invalidated to decide how to proceed in all queries. But… what happen when i get a object that is invalidated, and i want to replace it with a new object?

lets say

var a = realm.objects(dummy.self).first 

is invalidated
then i do

// if doesnt exist
if a == nil || a.isInvalidated {
// create new instance
  a = a()
}

realm.write {
a.prop = "something"
}

this is still crashing.

So my questions are:

  • Am i forced to create 2 variables ( ‘a’ and ‘b’ ) to avoid working with references ?
  • Why do we need to check isInvalidated all the time?
  • Does it have anything to do with realm auto refresh?
  • will refresh change the results from isInvaliddated==true to nil?
  • what should be the correct way to handle with objects that have been invalidated?

An object will not persist in a Results object if it’s been deleted - that’s the whole idea of a Results object. It’s a live connection to objects and if objects are added, changed or removed the Results object reflects that.

However, if an object has been deleted, and you’re holding a reference to it (as in var a in your code), it will be marked as invalidated which is different than what’s in the Results object.

In your example code, if an object doesn’t exist, you can’t create a ‘new instance’ of it - more than that though, a copy of a nil object is still a nil object and a copy of an existing object will point to the same data the initial object points to and that copy is still a managed object and cannot be modified outside of a write.

If you want to make a standalone ‘copy’ of an object, which is editable - here’s the pattern

let standaloneModelObject = MyModel(value: persistedModelObject)

This would be useful for example, if you want to edit the data from an object outside of a write and then perhaps write that data at a later time.

All of that being said - can you clarify what you’re trying to do and maybe we can provide a solution.

Thanks for the answer, I think I understand it better now.
My issue is… we have a project which is a bit messy, and we are getting crashes all over the app due Realm invalidated objects, I think this is caused because we are using multiple threads, we store data(realm objects) to use later, but when we are going to use the data the object was already invalidated, so the process shouldn’t even be executed or the code shouldn’t even get to this point.

So what we are trying to look is a way to ensure that when we are going to work with a object reference its not invalidated, if so we should refetch it or make it nil(our code handle it from here) to avoid the crashes.

Our nil validations are useless if the object is there but invalidated

While there is an option to check if a object isInvalidated and you could sprinkle that check throughout the code I think a better approach is to avoid the issue in the first place.

That may be part of the issue; from the Realm Docs

Don’t pass live objects, collections, or realms to other threads: Live objects, collections, and realm instances are thread-confined : that is, they are only valid on the thread on which they were created.

As mentioned previously, Realm objects are live updating and will always reflect the current state of the object. If you have a Results object that was populated by a query of uncompleted tasks, and then a task is marked completed (meaning it no longer matches the query) it will no longer be reflected in that Results object. If you’re seeing a different behavior then you’re probably passing that Result object (or and object in the results) around on different threads so they are then out of sync and will have invalidated objects.

Another possibility is a race condition caused by using transactions on one thread and then trying to access an object on another thread OR if you are using home-grown notifications to detect object changes instead of the built-in Realm notification process.