Open HackShitUp opened 1 year ago
I had the same issue. Server Side: "parse": "4.0.1", "parse-server": "^6.0.0"
IOS Client Side:
Apparently from some version of parse-server the received message from the ParseLiveQuery didn't return with the type on the main object in the string received. for example: { "op": "update", "clientId": "559ca4bd-7425-4ea8-b7ed-8ac73e6c6d15", "requestId": 2, "object": { "user1": { "type": "Pointer", "className": "_User", "objectId": "8YoD1R8RTJ" }, "user2": { "__type": "Pointer", "className": "_User", "objectId": "DrvZzHZASt" }, "createdAt": "2023-05-16T09:57:29.412Z", "updatedAt": "2023-05-20T20:13:46.736Z", "messages": { "type": "Relation", "className": "Message" }, "className": "PrivateChat", "objectId": "lsxP3br9EG" }, "original": { "user1": { "type": "Pointer", "className": "_User", "objectId": "8YoD1R8RTJ" }, "user2": { "__type": "Pointer", "className": "_User", "objectId": "DrvZzHZASt" }, "createdAt": "2023-05-16T09:57:29.412Z", "updatedAt": "2023-05-20T20:12:07.365Z", "messages": { "type": "Relation", "className": "Message" }, "className": "PrivateChat", "objectId": "lsxP3br9EG" } } As you can see "object" has no type so parse doesn't know how to parse it into a PFObject. that's why it says something like "bad json" when serializing it into PFObject.
So I've added a short code to always add a __type = "Object" into the Json for the first main "object" and I removed the original object, I don't see how original object is supported in the ParseLiveQuery-iOS-OSX library.
So the received json would now look like this: { "op": "update", "clientId": "559ca4bd-7425-4ea8-b7ed-8ac73e6c6d15", "requestId": 2, "object": { "user1": { "type": "Pointer", "className": "_User", "objectId": "8YoD1R8RTJ" }, "user2": { "__type": "Pointer", "className": "_User", "objectId": "DrvZzHZASt" }, "createdAt": "2023-05-16T09:57:29.412Z", "updatedAt": "2023-05-20T20:13:46.736Z", "messages": { "type": "Relation", "className": "Message" }, "__type": "Object", //This is what I've added, and removed "original" key from the json. "className": "PrivateChat", "objectId": "lsxP3br9EG" } }
So in the function func handleOperationAsync( string: String) -> Task
//--------START CHANGED CODE HERE------// var modifiedJson = jsonDecoded // Remove the "original" key if present modifiedJson.removeValue(forKey: "original")
if let object = modifiedJson["object"] as? [String: AnyObject] {
modifiedJson["object"] = addTypeToObject(object) as AnyObject
}
guard let response: ServerResponse = try? ServerResponse(json: modifiedJson) else {
throw LiveQueryErrors.InvalidResponseError(response: string)
}
func addTypeToObject(_ object: [String: AnyObject]) -> [String: AnyObject] {
var modifiedObject = object
for (key, value) in modifiedObject {
if key == "className" && !(value is [String: AnyObject]) {
modifiedObject["__type"] = "Object" as AnyObject
break
}
}
return modifiedObject
}
//--------END CHANGED CODE HERE------// switch response { case .connected: let sessionToken = PFUser.current()?.sessionToken self.subscriptions.forEach { _ = self.sendOperationAsync(.subscribe(requestId: $0.requestId, query: $0.query, sessionToken: sessionToken)) }
case .redirect:
// TODO: Handle redirect.
break
case .subscribed(let requestId):
self.subscriptionRecord(requestId)?.subscribeHandlerClosure(self)
case .unsubscribed(let requestId):
guard
let recordIndex = self.subscriptions.firstIndex(where: { $0.requestId == requestId })
else {
break
}
let record: SubscriptionRecord = self.subscriptions[recordIndex]
record.unsubscribeHandlerClosure(self)
self.subscriptions.remove(at: recordIndex)
case .create, .delete, .enter, .leave, .update:
var requestId: RequestId = RequestId(value: 0)
guard
let event: Event<PFObject> = try? Event(serverResponse: response, requestId: &requestId),
let record = self.subscriptionRecord(requestId)
else {
break
}
record.eventHandlerClosure(event, self)
case .error(let requestId, let code, let error, let reconnect):
let error = LiveQueryErrors.ServerReportedError(code: code, error: error, reconnect: reconnect)
if let requestId = requestId {
self.subscriptionRecord(requestId)?.errorHandlerClosure(error, self)
} else {
throw error
}
}
}
}
I hope that this will be taken care of by the library itself cause if I update the library I will always have to remember to add this code. Perhaps if there's is no type assume that it is "__type" = "Object" or something if it's missing, not really sure what the best way would be. but I would appreciate it if this can be fixed internally.
Much blessings
Does anyone want to open a PR and propose a solution?
@432player, @HackShitUp The LiveQuery feature has been added as a module to the Parse Apple SDK; could you please verify that this issue is fixed there, and if not open a new issue there?
New Issue Checklist
Issue Description
The
Subscription.handleEvent
protocol never gets called but WebSocket pings are received (logged inClient.shouldPrintWebSocketTrace
)Steps to reproduce
Define the client, and subscribe to a query the standard way:
WebSocket trace logs received ping but does not forward to the protocol.
Actual Outcome
Event not forwarded at the ParseLiveQuery layer
Expected Outcome
All emitted events should be accessible by the Subscription's handler
Environment
Parse LiveQuery ObjC SDK
2.8.1
1.5.0
1.19.0
iOS 16.0
Server
5.4.1
Remote/Local