I am updating an iOS app using ParseSwift. In general, every ParseUser of the app has several associated Userdata ParseObjects that need to be queried or fetched.
The current implementation uses individual queries to find every individual Userdata object one after the other. This works but is obviously not optimal.
What I already reworked is that every ParseUser now saves an Array of objectId's of the user-associated Userdata ParseObjects.
What I am trying to achieve now is to query for all Userdata objects that correspond to these saved objectId's in the ParseUser's userdataIds field.
This is my code:
func asyncAllUserdataFromServer() {
let userdataIdArray = User.current!.userdataIds
var objectsToBeFetched = [Userdata]()
userdataIdArray?.forEach({ objectId in
let stringObjectId = objectId as String
// create a dummy Userdata ParseObject with stringObjectId
let object = Userdata(objectId: stringObjectId)
// add that object to array of Userdata objects that need to be fetched
objectsToBeFetched.append(object)
})
// fetch all objects in one server request
objectsToBeFetched.fetchAll { result in
switch result {
case .success(let fetchedData):
// --- at this point, fetchedData is a ParseError ---
// --- here I want to loop over all fetched Userdata objects ---
case .failure(let error):
...
}
}
}
I read in the ParseSwift documentation that several objects can be fetched at the same time based on their objectIds, so my idea was to create an Array of dummy Userdata objects with the objectIds to fetch. This, however, does not work.
As indicated in the code block, I was able to narrow the error down, and while the query is executed, fetchedData
comes back as a ParseError
saying:
Error fetching individual object: ParseError code=101 error=objectId "y55wmfYTtT" was not found in className "Userdata"
This Userdata object with that objectId is the first (and only) objectId saved in the User.current.userdataIds array. This object does exist on my server, I know that for sure.
Any ideas why it cannot be fetched?
General infos:
Edit:
User implementation:
struct User: ParseUser {
//: These are required by `ParseObject`.
var objectId: String?
var createdAt: Date?
var updatedAt: Date?
var ACL: ParseACL?
//: These are required by `ParseUser`.
var username: String?
var email: String?
var emailVerified: Bool?
var password: String?
var authData: [String: [String: String]?]?
//: Custom keys.
var userdataIds: [String]? // --> array of Userdata objectId's
}
Userdata implementation:
struct Userdata: ParseObject, ParseObjectMutable {
var objectId: String?
var createdAt: Date?
var updatedAt: Date?
var ACL: ParseACL?
var firstname: String?
var lastSeen: Int64?
var isLoggedIn: Bool?
var profilepicture: ParseFile?
}
You should check your Class Level Permissions (CLP's) and here in Parse Dashboard, if you are using the default configuration, you can’t query the _User
class unless you make the CLP’s public or authorized. In addition, you can probably shrink your code by using a query and finding the objects instead of building your user objects and fetching the way you are doing:
let userdataIdArray = User.current!.userdataIds
let query = Userdata.query(containedIn(key: "objectId", array: userdataIdArray))
//Completion block
query.find { result in
switch result {
case .success(let usersFound):
...
case .failure(let error):
...
}
}
// Async/await
do {
let usersFound = try await query.find()
...
} catch {
...
}
You should also look into your server settings to make sure this option is doing what you want it to do: https://github.com/parse-community/parse-server/blob/4c29d4d23b67e4abaf25803fe71cae47ce1b5957/src/Options/docs.js#L31