Backendless Support
 
Solved

fatal error: NSArray element failed to match the Swift Array Element type for relational array

SDK: v3.1.0

There are people who can be in multiple groups. With groups being autoloaded

  1. class Person: NSObject {
  2. var name: String?
  3. var groups: [Group] = []
  4. }

  1. class Group: NSObject {
  2. var name: String?
  3. }

I save a group to each person using this function:

  1. func saveByAsync(_ person: Person, completionHandler: ((_ person: Person?) -> Void)? = nil) {
  2. dataStore?.save(person, response: { result -> Void in
  3. completionHandler?(result as! Person)
  4. }, error: { fault -> Void in
  5. print("Server reported an error (save person async): \(String(describing: fault))")
  6. completionHandler?(nil)
  7. })
  8. }

Then I want to find all the people that are in a certain group:

  1. func findPeopleByAsync(in group: Group, completionHandler: @escaping (_ people: [Person]) -> Void) {
  2. let whereClause = "groups.name = '\(group.name!)'"
  3. let dataQuery = BackendlessDataQuery()
  4. dataQuery.whereClause = whereClause
  5. dataStore?.find(dataQuery, response: { (result) in
  6. let people = result?.getCurrentPage() as! [Person]
  7. for obj in people {
  8. for group in obj.groups {
  9. print("Person = \(String(describing: group))") // Error here
  10. }
  11. }
  12. completionHandler(people)
  13. }, error: { fault in
  14. print("Server reported an error: \(String(describing: fault))")
  15. })
  16. }

But when I examine each person, a person with multiple groups has an array like this

  1. person.groups = [Group, [Group]]

Or even

  1. person.groups = [[String, String]]

When I save, a group into a person, I'm checking each save and I don't create anything like this. When you check the console data table, everything is fine and nothing resembles that. My hypothesis is that this happens in the SDK and during the parsing function?

This problem doesn't happen only if I search for specific people with a group name. This happens when I want to call all the people as well.

Leave a Comment

Comments (21)

photo
1

Hi Brian,

Are you saying you get person objects back with groups a person does not belong to?

Btw, we do not have SDK version 3.1.0. It should be something line 3.0.X - please check what that "X" is in your case and better yet, make sure to update to the latest version (3.0.46)

Mark

photo
1

It should be giving me the correct groups. The problem is is that person.groups is suppose to be [Groups] but it's not. It's person.groups = [Group, [Group]], if the person is in two groups. Because of this I get an error fatal error: NSArray element failed to match the Swift Array Element type for relational array.

You're right. It is the latest version though, 3.0.46

photo
1

Could you attach a screenshot from the debugger showing what you get?

photo
1

It just shows fatal error: NSArray element failed to match the Swift Array Element type for relational array.

photo
1

You're saying the data returned from the server is:

  1. person.groups = [Group, [Group]]

How do you know that? Can you attach a screenshot showing us what you see?

photo
1

This is [[String, String]]

cb585fd704060608b7c9c9c33fb7acf2

This is somewhat like [Group, [Group]] but all it did was [[Group]]

3c3b27f50367743b6a4e1212a08bf486

photo
1

It is an array of one group, which I turn contains an array of two strings.

photo
1

Yes, and that causes an array because it's expecting to be [Group]

photo
1

Please post the source code for the Ryze.Group class and let us know your application ID.

photo
1

It's already in the initial post.

app id: 3562E910-193E-F469-FFA8-DF25DFDCA000

photo
1

  1. Is the Group class defined is a separate .swift file? Such as Group.swift ?
  2. What happens to the "color" property? It is in the database, but not defined in the class.

photo
1

1. Yes

2. color property is there in the class

photo
1

The "color" property is not in the original post. Could you post the entire contents of the Group.swift file?

Also, you have custom business logic for the Person table. Please temporarily disable the event handlers and try retrieving objects again - this will make sure that the business logic does not introduce any changes.

photo
1

That's about it

  1. class Group: NSObject {
  2. var name: String?
  3. var color: String?
  4. }

Thanks for the suggestion. After disabling the event handler, it works. BUT the event handler we have does not modify groups.

afterFind event handler

  1. Backendless.ServerCode.Persistence.afterFind('Person', (req, res) => {
  2. if(res.result.data && res.result.data.length > 0) {
  3. for(let i = 0; i < res.result.data.length; i++) {
  4. res.result.data = appendStatus(res.result.data);
  5. }
  6. }
  7. });

and appendStatus

  1. const appendStatus = (person) => {
  2. if (person && Array.isArray(person.reminders) && person.reminders[0]) {
  3. // NOTE: this uses the FIRST reminder!
  4. const reminder = person.reminders[0],
  5. notifyDate = reminder.notifyDate,
  6. notifyMoment = moment.utc(notifyDate)
  7. if (moment.utc().isBefore(notifyMoment)) {
  8. person.status = {"___class": "Status", "status": "early", "title": notifyMoment.fromNow()};
  9. } else {
  10. person.status = {"___class": "Status", "status": "late", "title": notifyMoment.fromNow()};
  11. }
  12. } else {
  13. person.status = {"___class": "Status", "status": "none", "title": null};
  14. }
  15. return person;
  16. };

photo
1

Thanks for verifying. This is a regression we found earlier today in another app. The problem is the CodeRunner may break object fidelity when the object is sent to/from the CodeRunner. We're working on a fix and it should be available shortly.

photo
1

Glad to hear you found the culprit. Thanks for the help!

photo
photo
1

Any updates?

photo
1

Got any good news? :)

photo
1

Hi Brian,

An engineer is working on the problem. We will update this topic when a fix becomes available.

Regards,

Mark

photo
photo
1

Hi Brian,

we have fixed the issue, can you check it again?

photo
1

It works! Thank you!

photo