Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS ParseError : Attempted to change an objectId to one that's already known to the Offline Store

I'm having a regular issue with my project, using Parse Server. First, I call a Parse Cloud function to populate a user's data list :

var dataSet: Set<MyData>?

func loadData(withParameters parameters: [String : Any]) {

        PFCloud.callFunction(inBackground: "loadData", withParameters: parameters) { (success, error) in

            if let objects = success as? [[String : Any]] {

                let dataTable: [MyData] = objects.map({ (object) -> MyData in

                    let myData = MyData(dataSource: PFObject(className: "MyData", 
                                        dictionary: object))
                    myData.dataSource?.objectId = object["objectId"] as? String
                    return myData
                })

                if self.dataSet == nil {
                    self.dataSet = []
                }

                self.dataSet = Set(dataTable)
            }
        }
    }

On the code mentioned above, I have to set the objectId because without this, no matter how many objects I fetch from Parse, when I reduce the array to a set with the last instruction I end up with only one object in it.

However, although this works, when I call this function again to update user's data, I get this error on the myData.dataSource?.objectId = temp["objectId"] as? String line :

Attempted to change an objectId to one that's already known to the Offline Store.

Tried to find some information about it but nothing very relevant...

Thanks for your help.

like image 985
Rob Avatar asked Oct 29 '22 00:10

Rob


1 Answers

This is no really an answer, but too long for a comment:

I understand the following:
Your cloud function loadData returns success, which is an array of dictionaries or, probably in case of an error, nil. If nil is returned, you do nothing.
If an array is returned, it is referred as objects.
This array is then mapped to an array of elements of type MyData.
For every element returned from the cloud function, called object, a MyData instance is created using as dataSource a new PFObject instance of class MyData and properties given by the object dictionary.
I do not understand the next statement by which you assign the objectId of the object returned from the cloud function to the newly created PFObject: As far as I know, objectIds must be unique, and cannot (or at least should not) be assigned to other PFObjects.
But you said you have to do this or otherwise you end up with a single element in the resulting set (see below).
Anyway, you have now an array of MyData instances in dataTable.
Then, you initialise dataSet, which is not required since it will be overwritten anyway by your last statement.
This statement makes a set of the dataTable array.

Now, when you get a single element in this set in case you do not set the objectId property of the elements of the dataTable array, this means that all elements of this array are the same object. And this means that your init function

MyData(dataSource: PFObject(className: "MyData", 
                                        dictionary: object))  

returns always the same object, and this object is made to a different one by setting its objectId property. This is very strange to me. Please check what it going on there.

Now if you call loadData once more to update the data, the cloud function probably returns some or all of the previous objects again. In this case, you would assign an old objectId, that has already been assigned earlier to a PFObject created in the map function, to another newly created PFObject created there, which is not allowed, thus the error message.

To cut it short:
If the same object is returned from the cloud function repeatedly, you must not create different PFObjects for them, and assign them the same objectId.

I hope this helps!

like image 76
Reinhard Männer Avatar answered Nov 15 '22 07:11

Reinhard Männer