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

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

我使用 Parse Server 的项目经常遇到问题。首先,我调用 Parse Cloud 函数来填充用户的数据列表:

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)
            }
        }
    }

在上面提到的代码中,我必须设置 objectId 因为没有这个,无论我从 Parse 中获取多少对象,当我用最后一条指令将数组缩减为一个集合时,我最终会里面只有一个物体。

然而,尽管这可行,但当我再次调用此函数更新用户数据时,我在 myData.dataSource?.objectId = temp["objectId"] as? String 行收到此错误:

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

试图找到一些关于它的信息,但没有什么非常相关的...

感谢您的帮助。

这不是一个真正的答案,但对于评论来说太长了:

我了解以下内容:
您的云函数 loadData returns success,它是一个字典数组,或者,如果出现错误,可能是 nil。如果返回 nil,则您什么都不做。
如果返回一个数组,它被称为 objects.
然后将该数组映射到 MyData.
类型的元素数组 对于从云函数返回的每个元素,称为 object,使用 dataSource 新的 PFObject 实例创建一个 MyData 实例class MyData 和对象字典给出的属性。
我不明白您将云函数返回的对象的 objectId 分配给新创建的 PFObject 的下一条语句: 据我所知,objectIds 必须是唯一的,并且不能(或至少不应该)分配给其他 PFObjects.
但是你说你必须这样做,否则你最终会在结果集中得到一个元素(见下文)。
无论如何,您现在在 dataTable.
中有一个 MyData 实例数组 然后,您初始化 dataSet,这不是必需的,因为它无论如何都会被您的最后一条语句覆盖。
此语句生成一组 dataTable 数组。

现在,如果您没有设置 dataTable 数组元素的 objectId 属性,则当您在该集合中获取单个元素时,这意味着所有元素这个数组的是同一个对象。这意味着你的初始化函数

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

returns总是同一个对象,通过设置它的objectId属性使这个对象变成不同的对象。这对我来说很奇怪。请检查那里发生了什么。

现在,如果您再次调用 loadData 来更新数据,云函数可能会再次 returns 之前的部分或全部对象。在这种情况下,您会将一个旧的 objectId 分配给之前已分配给在 map 函数中创建的 PFObject 的另一个新创建的 PFObject,这是不允许的,因此错误消息。

长话短说:
如果从云函数中重复返回同一个对象,则不能为它们创建不同的PFObjects,并为它们赋值相同的objectId

希望对您有所帮助!

http://parseplatform.org/Parse-SDK-iOS-OSX/api/Protocols/PFSubclassing.html

If a subclass of PFObject conforms to PFSubclassing and calls PFObject.+registerSubclass, Parse framework will be able to use that class as the native class for a Parse cloud object.

例如:

1.Create 你的 PFObject 子类

import Parse

class Question: PFObject, PFSubclassing {

    @NSManaged var category: String?
    @NSManaged var text: String
    @NSManaged var image: PFFile?
    @NSManaged var answerType: String
    @NSManaged var order: NSNumber

    static func parseClassName() -> String {
        return "Question"
    }
}

class User: PFUser {

    @NSManaged var fullname: String
}

2.Register 子类

extension Parse {
    class func registerSubclasses() {
        User.registerSubclass()
        Question.registerSubclass()
    }
}

3.Configure 应用启动后解析服务

Parse.registerSubclasses()
Parse.enableLocalDatastore()
Parse.setApplicationId(PARSE_APP_ID, clientKey: PARSE_APP_KEY)

4.Now PFUser == User, Question == PFObject(className: "Question")

5.It 适用于 Cloud Function

PFCloud.callFunctionInBackground("fetchQuestions", withParameters: parameters) { questions, error in
            if let questions = questions as? [Question] {
                completion?(questions, nil)
            } else {
                completion?(nil, error)
            }
        }

注意:swift 代码可能较旧,如果使用更高的 swift 版本,应该会有一些变化。