Skip to content

Array of Pointer not working in User class #130

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
ghost opened this issue Apr 26, 2021 · 7 comments
Closed

Array of Pointer not working in User class #130

ghost opened this issue Apr 26, 2021 · 7 comments
Labels
type:question Support or code-level question

Comments

@ghost
Copy link

ghost commented Apr 26, 2021

Hey Parse-Community!

I'm trying to get an array of pointers from a user.
This works perfectly with a logged in user.

User.current?.fetch(includeKeys: ["pointerArray"], options: [], callbackQueue: .main, completion: { result in
    // Do stuff
}

But when logging in for the first time it doesn't work.

User.login(username: username, password: password) { results in
   // Do stuff
}

I get the following error:

ParseError(code: ParseSwift.ParseError.Code.unknownError, message: "Error decoding parse-server response: {...} with error: The data couldn’t be read because it is missing. Format: {...} 

The Objects:

struct User: ParseUser, Codable {
    var username: String?
    var email: String?
    var password: String?
    var authData: [String: [String: String]?]?
    var objectId: String?
    var createdAt: Date?
    var updatedAt: Date?
    var ACL: ParseACL?

    var pointerArray: [CustomObject]?
}

struct CustomObject: ParseObject, Codable {
    var objectId: String?
    var createdAt: Date?
    var updatedAt: Date?
    var ACL: ParseACL?

    var title: String?
}
@cbaker6 cbaker6 added the type:question Support or code-level question label Apr 26, 2021
@cbaker6
Copy link
Contributor

cbaker6 commented Apr 26, 2021

Hi @Mammut-Felix, when posting a potential issue, please post the full ParseError as it often shows where the problem is. You can remove any private info.

Also, is the struct you provided what you actually tested. You originally posted:

struct User: ParseUser, Codable {
    var username: String?
    var email: String?
    var password: String?
    var authData: [String: [String: String]?]?
    var objectId: String?
    var createdAt: Date?
    var updatedAt: Date?
    var ACL: ParseACL?

    var pointerArray: [CustomObject] // Not optional, which will definitely give you an error because all keys should be optional
}

These are not the same...

You can see this answer for more details as from you original post it seems like the same problem.

@ghost
Copy link
Author

ghost commented Apr 26, 2021

Hi @cbaker6, thanks for your reply.
Yeah I changed the post because I forgot the optional. In my test the array is also optional.

The complete ParseError:

ParseError(code: ParseSwift.ParseError.Code.unknownError, message: "Error decoding parse-server response: Optional(<NSHTTPURLResponse: 0x6000018d9800> { URL: https://parse.endpoint/login } { Status Code: 200, Headers {\n    \"Access-Control-Allow-Origin\" =     (\n        \"*\"\n    );\n    \"Content-Encoding\" =     (\n        gzip\n    );\n    \"Content-Type\" =     (\n        \"application/json; charset=utf-8\"\n    );\n    Date =     (\n        \"Mon, 26 Apr 2021 11:42:53 GMT\"\n    );\n    Etag =     (\n        \"W/\\\"1ef-EOV9mGaVgYexdK/WN2AMiTxS3P8\\\"\"\n    );\n    Server =     (\n        nginx\n    );\n    \"Strict-Transport-Security\" =     (\n        \"max-age=31536000; includeSubDomains; preload\"\n    );\n    Vary =     (\n        \"Accept-Encoding\"\n    );\n    \"access-control-allow-headers\" =     (\n        \"X-Parse-Master-Key, X-Parse-REST-API-Key, X-Parse-Javascript-Key, X-Parse-Application-Id, X-Parse-Client-Version, X-Parse-Session-Token, X-Requested-With, X-Parse-Revocable-Session, X-Parse-Request-Id, Content-Type, Pragma, Cache-Control\"\n    );\n    \"access-control-allow-methods\" =     (\n        \"GET,PUT,POST,DELETE,OPTIONS\"\n    );\n    \"access-control-expose-headers\" =     (\n        \"X-Parse-Job-Status-Id, X-Parse-Push-Status-Id\"\n    );\n    \"content-security-policy\" =     (\n        \"default-src \'self\' http: https: data: blob: \'unsafe-inline\'\"\n    );\n    \"referrer-policy\" =     (\n        \"no-referrer-when-downgrade\"\n    );\n    \"x-content-type-options\" =     (\n        nosniff\n    );\n    \"x-frame-options\" =     (\n        SAMEORIGIN\n    );\n    \"x-powered-by\" =     (\n        Express\n    );\n    \"x-xss-protection\" =     (\n        \"1; mode=block\"\n    );\n} }) with error: The data couldn’t be read because it is missing. Format: Optional(\"{\\\"objectId\\\":\\\"w6d9Be0kUW\\\",\\\"emailVerified\\\":true,\\\"username\\\":\\\"[email protected]\\\",\\\"accType\\\":\\\"admin\\\",\\\"createdAt\\\":\\\"2021-03-22T13:57:47.210Z\\\",\\\"updatedAt\\\":\\\"2021-04-26T11:41:55.265Z\\\",\\\"email\\\":\\\"[email protected]\\\",\\\"firstname\\\":\\\"firstname\\\",\\\"lastname\\\":\\\"lastname\\\",\\\"pointerArray\\\":[{\\\"__type\\\":\\\"Pointer\\\",\\\"className\\\":\\\"CustomObject\\\",\\\"objectId\\\":\\\"ghB7KjzWSQ\\\"}],\\\"ACL\\\":{\\\"*\\\":{\\\"read\\\":true},\\\"role:Admin\\\":{\\\"read\\\":true,\\\"write\\\":true},\\\"w6d9Be0kUW\\\":{\\\"read\\\":true,\\\"write\\\":true}},\\\"sessionToken\\\":\\\"r:9121a3ece6de6e0588e49b5e187c7ccf\\\"}\")")

At the CustomObject all properties are optional, too.

@cbaker6
Copy link
Contributor

cbaker6 commented Apr 26, 2021

Something doesn't seem right with your code. The error states: The data couldn’t be read because it is missing. which usually indicates it couldn't decode a required key, but you are saying everything is optional and works when you includeKeys: ["pointerArray"],.... Are you sure you only have one User struct and all the keys are optional? What happens when you comment out pointerArray in your User struct and then login?

struct User: ParseUser, Codable {
    var username: String?
    var email: String?
    var password: String?
    var authData: [String: [String: String]?]?
    var objectId: String?
    var createdAt: Date?
    var updatedAt: Date?
    var ACL: ParseACL?

    //var pointerArray: [CustomObject] // Not optional, which will definitely give you an error because all keys should be optional
}

It looks like your ParseUser doesn't match your server as your server is giving you back properties like accType, etc. This shouldn't be causing your issue, but you will need to add them to your User struct if you intend to use them on the client in the future.

All ParseObjects are Encodable and Decodable, you shouldn't need to add Codable, I would imagine the compiler is giving you warning.

@cbaker6
Copy link
Contributor

cbaker6 commented Apr 26, 2021

Be sure to verify your code against the example in playgrounds:

//: Pointer array.
let otherBook1 = Book(title: "I like this book")
let otherBook2 = Book(title: "I like this book also")
var author2 = Author(name: "Bruce", book: newBook)
author2.otherBooks = [otherBook1, otherBook2]
author2.save { result in
switch result {
case .success(let savedAuthorAndBook):
assert(savedAuthorAndBook.objectId != nil)
assert(savedAuthorAndBook.createdAt != nil)
assert(savedAuthorAndBook.updatedAt != nil)
assert(savedAuthorAndBook.ACL == nil)
assert(savedAuthorAndBook.otherBooks?.count == 2)
print("Saved \(savedAuthorAndBook)")
case .failure(let error):
assertionFailure("Error saving: \(error)")
}
}

Querying:

//: Query for your new saved author
let query1 = Author.query("name" == "Bruce")
query1.first { results in
switch results {
case .success(let author):
print("Found author: \(author)")
case .failure(let error):
assertionFailure("Error querying: \(error)")
}
}
/*: You will notice in the query above, the fields `book` and `otherBooks` only contain
arrays consisting of key/value pairs of `objectId`. These are called Pointers
in `Parse`.
If you want to retrieve the complete object pointed to in `book`, you need to add
the field names containing the objects specifically in `include` in your query.
*/
/*: Here, we include `book`. If you wanted `book` and `otherBook`, you
could have used: `.include(["book", "otherBook"])`.
*/
let query2 = Author.query("name" == "Bruce")
.include("book")
query2.first { results in
switch results {
case .success(let author):
print("Found author and included \"book\": \(author)")
case .failure(let error):
assertionFailure("Error querying: \(error)")
}
}
/*: When you have many fields that are pointing to objects, it may become tedious
to add all of them to the list. You can quickly retreive all pointer objects by
using `includeAll`. You can also use `include("*")` to retrieve all pointer
objects.
*/
let query3 = Author.query("name" == "Bruce")
.includeAll()
query3.first { results in
switch results {
case .success(let author):
print("Found author and included all: \(author)")
case .failure(let error):
assertionFailure("Error querying: \(error)")
}
}

@cbaker6
Copy link
Contributor

cbaker6 commented Apr 26, 2021

I've added another example to ParseUser in playgrounds that uses a ParseObject array similar to your example called allScores.

/*: Save your first `customKey` value to your `ParseUser`
Asynchrounously - Performs work on background
queue and returns to specified callbackQueue.
If no callbackQueue is specified it returns to main queue.
*/
User.current?.customKey = "myCustom"
User.current?.score = GameScore(score: 12)
User.current?.targetScore = GameScore(score: 100)
User.current?.allScores = [GameScore(score: 5), GameScore(score: 5)]
User.current?.save { results in
switch results {
case .success(let updatedUser):
print("Successfully save custom fields of User to ParseServer: \(updatedUser)")
case .failure(let error):
print("Failed to update user: \(error)")
}
}

The playground examples work which leads me to believe something is wrong with your code. You should look through the examples and verify your code is setup properly.

@ghost
Copy link
Author

ghost commented Apr 28, 2021

@cbaker6 Thank you for your support. I've got it going now. The error was actually in the CustomObject

@cbaker6
Copy link
Contributor

cbaker6 commented Apr 28, 2021

Can you post what the error was and your your fix just in case someone else has the same issue in the future?

Feel free to close this issue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type:question Support or code-level question
Projects
None yet
Development

No branches or pull requests

1 participant