Skip to content
This repository has been archived by the owner on Sep 5, 2023. It is now read-only.

no kvc automatic conversion of string to basic type when overriding mts_validateValue #16

Closed
jpmhouston opened this issue Oct 2, 2014 · 3 comments

Comments

@jpmhouston
Copy link

The automatic conversion of strings to basic type where "value is generated automatically by KVC" as described in the chart, that seems to not work when overriding mts_validateValue:forKey:error: for when objects are NSManagedObjects. Leads to the following exception throw from setValue:forKey:

Description of exception being thrown: 'Unacceptable type of value for attribute: property = "latitude"; desired type = NSNumber; given type = __NSCFString; value = 0.01.'

I was pleasantly surprised to find most of the Motis automatic conversions noted in the chart do get performed when mts_validateValue:forKey:error: is overridden, as first read of the documentation gave me the impression that it wouldn't. But I found this hiccup, and firstly I'd like to know if this is just one of several conversions that won't work for one reason or another when skipping the call to validateValue:forKey:error:.

Because if it's just the doubles and other ints, except the ones with special cases in mts_validateAutomaticallyValue:forKey: like BOOL & unsigned long long, then secondly, why not add a few more cases to mts_validateAutomaticallyValue:forKey: for this situation? I've tried added cases for double, NSInteger & NSUInteger and it seems to avoid the exception noted above. I'll be submitting a pull request.

@vilanovi
Copy link
Contributor

vilanovi commented Oct 2, 2014

Hello @jpmhouston,

Thanks for your comments. I really appreciate all kind of feedback that may improve Motis.

First of all, as you might noticed, Motis performs a two-step verification process:

First, using the method "mts_validateValue:forKey:error" (which by default triggers the KVC validation), gives an option to the user to manually validate values. If using the KVC pattern for validation, the default implementation of KVC methods does nothing and it is the developer responsibility to create methods as "validate:error:" for each key to validate.

When using Core Data, you must override the method "mts_validateValue:forKey:error" and do any manual validation directly in there. The KVC validation pattern cannot be used as it is being used by Core Data.

Second, if the user didn't provide a manual validation for a given key, Motis is triggering an automatic validation process, in which will attempt to convert the "input type" of the value into the final key property type, and if it fails, the value won't be assigned. This is done in the method "mts_valiateAutomaticallyValue:forKey:" (lines 267 and 271 of NSObject+Motis.m). The automatic conversions chart available in the Motis documentation references this process of automatic validation and not the KVC validation pattern (which by default does nothing).

For conversions of type string --> basic type, different approaches are used. In line 775 of NSObject+Motis.m we are handling the case of having as input an string and a basic type as the key property type. Because in the final step the value will be assigned using the KVC setter, if assigning an string to a property of basic type, KVC will use the methods: doubleValue, floatValue, intValue, integerValue, longLongValue or boolValue. However, there are 2 more cases to be handled: unsigned long long types and the case of "true"/"false" for booleans.

However, as you are reporting, the KVC setter seems to not work as expected when using it with Core Data, which probably is overriding the KVC getters/setters.

A solution could be to use instead "NSNumberFormatter" to convert �strings to numbers. However, the usage of this class is very expensive in performance and I would like to avoid to use it as much as possible.

In any case, thanks for your bug report, I'll try to reproduce the issue an think for a solution. Also, you are welcome to submit a pull request if you can fix it.

Thanks,

Joan

@jpmhouston
Copy link
Author

So I had it wrong, it wasn't specifically the mts_valiateAutomaticallyValue:forKey: override that's preventing the KVC conversions, but instead some other aspect of having model objects subclassed off NSManagedObject. Makes sense.

I may still do my fork which will add more special cases in addition to unsigned long long and "true"/"false" booleans (with full knowledge of them being redundant when Core Data not in the picture), but first I will look again at doing this in mts_valiateAutomaticallyValue:forKey: instead.

@vilanovi
Copy link
Contributor

OK. Just send a pull request if you do any improvement.

Thanks

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants