Error if optional UIImage has a value when saving

using iOS SDK version 7.0.1

I have a class with an optional UIImage:

@Published var testPic: UIImage?

if I save the object when the value is nil then everything is fine, but if I assign a value to the testPic and try to save I get this error:

*** Terminating app due to uncaught exception ‘NSUnknownKeyException’, reason: ‘[<NSObject 0x1e4628f58> valueForUndefinedKey:]: this class is not key value coding-compliant for the key objectId.’
*** First throw call stack:
(0x192fde5e0 0x18b30fc00 0x193063248 0x191fb23d0 0x191e90f7c 0x10553cd38 0x105541b14 0x105541cc4 0x105541558 0x105541cc4 0x105541558 0x1054609c4 0x10546027c 0x102c1429c 0x102c14aa0 0x104ef4f50 0x104ef6b34 0x104f06fec 0x104f06ba0 0x192f289bc 0x192f256c8 0x192f24e18 0x1d59e55ec 0x195333350 0x19533298c 0x197cfb354 0x197cfb198 0x197978434 0x102faa0d0 0x102faa180 0x1b570bd44)
libc++abi: terminating due to uncaught exception of type NSException

I use this to save:

animalStore.save(entity: animal) { savedAnimal in 

} catch {
 print(error)
}

Hello @David_Thompson,

Backendless stores images as files, not as objects.
You should upload your image as a file and then store its URL in the File Reference column as a string.

Regards,
Stanislaw

Thanks @stanislaw.grin for the comment. Yes, I do store the images as files and I only keep the reference in BE. I have the image in the object so I can pass it around after it’s loaded. I think the expected behavior would be that BE ignores unsupported data types. @olhadanylova has a tutorial for a chat-app that uses this same approach. Here is a screenshot:

I have other classes with unsupported data types too…like custom objects, etc. Should I worry that those will cause problems too? I’m just not sure the official approach to those types…

thanks
david

Thanks for the clarification @David_Thompson, we will check it and @olhadanylova will contact you later.

Hi @David_Thompson ,

The tutorial and example you’re looking at are quite old (that app was creted 5 years ago as git says).

The mentioned example works with an old library, based on AMF.
I cannot tell exactly how it works there (this lib is not supported for years now), but right now the Backendless-Swift library works on REST and as @stanislaw.grin said, Backendless stores images as files, not as objects.

Please use this approach (it is actual and correct):

upload your image as a file and then store its URL in the File Reference column as a string.

Regards,
Olha

Hi @olhadanylova, thank you for the feedback.

I am storing the URL in the File Reference column, and I’m only using the UIImage as a location to store the image after I have loaded it. I’m not trying to store the UIImage in Backendless via the save method.

I was surprised that it caused a parsing problem because I have other data types in classes that are not stored in Backendless and those have not caused problems…at least not yet?

The real question is what to do with data types used by the client and not stored in Backendless? Should the SDK just ignore them? That is what I thought it did. Or is it advised that we maintain a separate class only for storing items in Backendless and another class for client usage?

The real question is what to do with data types used by the client and not stored in Backendless? Should the SDK just ignore them? That is what I thought it did. Or is it advised that we maintain a separate class only for storing items in Backendless and another class for client usage?

I see. Unfortunately right now Swift-SDK doesn’t support property ignoring. I’ve created an internal ticket to investigate possible ways to solve this issue. Unfortunately, couldn’t provide any estimates right now, but will respond to you as soon as possible.

ok, thanks for looking into this. I did a little digging and we could possibly filter at this function:

PersistenceHelper → entityToSimpleType()

Yeah, I know about that method :grinning:. I mean, can make a workaround to ignore all incompatible types. But we discussed this question and final fix could take more time for for longer perspective.

ok thank you…i have other parts to code so I’ll just wait to move forward on this part.

Thanks for your patience and sorry for inconvenience. Working on it right now.

Hello @David_Thompson,

A new version of Swift-SDK (7.0.3) allows you to exclude properties from interacting with Backendless db.
Please use this method to exclude properties for classes:

Backendless.shared.data.excludeProperties(forClass: AnyClass, fieldNames: [String])

ok…does this mean I need to add this line before every interaction with the db? Something like this:

Backendless.shared.data.excludeProperties(forClass: Animal.self, fieldNames: ["testPic"])
animalStore.save(entity: animal) { savedAnimal in 

} catch {
    print(error)
}

Is the recommended practice to have the excludedProperties array stored in the class (also including itself)? I’m just trying to figure out the best approach and where to store this list. Maintaining an exclusion array seems hard to maintain and potentially error prone if I forget to add a property or if I forget to add the exclusion statement before a db interaction.

I can make this work for now, and thank you for adding this feature. I’m hoping there is some consideration in a future release for the SDK just dropping unsupported property types silently instead of a manual list. I have a LOT of unsupported property types (think every custom class). It will take some work to create an exclusion array for all classes and add exclusion statements to all db calls.

to be clear I DO think an exclusion list gives the client more flexibility, but I think it adds complexity.

Hi @David_Thompson,
You can call

Backendless.shared.data.excludeProperties(forClass: Animal.self, fieldNames: ["testPic"])

from any point of your code.

I’m hoping there is some consideration in a future release for the SDK just dropping unsupported property types silently instead of a manual list.

We discussed this task and decided to leave only the list of excluded properties for now. Unfortunately, Swift property wrappers don’t allow to handle properties for exclusion like it is done in Android with annotations.

it adds complexity

However, you can place all of the excluded properties for different classes at one place in the code and it’ll be easy to edit that list if necessary.

ok I think I understand …I only need to run that line ONCE for each class and not before every db interaction. So this could be done on startup/loading phase?

I tried this:

let animalStore = Backendless.shared.data.of(Animal.self)
Backendless.shared.data.excludeProperties(forClass: Animal.self, fieldNames: ["animalPic"])
animalStore.save(entity: animal) { savedAnimal in
    print("Found animals: \(savedAnimal)")
    dismiss()
} errorHandler: { fault in
    print("Error: \(fault.message ?? "")")
}

for this property in the Animal class:

 @Published var animalPic: UIImage?

and I got the same error.

If I set this property to nil like this…

var tmp = animal.animalPic
animal.animalPic = nil
saveHorse() //run save function here
animal.animalPic = tmp

and then set it back to the image it works fine. There is something about the UIImage property being set with a value that it doesn’t like.

Looking into it.

@David_Thompson, please try with v7.0.4.

The exclusion list works with 7.0.4…still trying to wrap my mind around this approach. I’ll work with it a bit. thank you.

1 Like