Skip to content
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

Custom setter with error out parameter #564

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

Krizai
Copy link

@Krizai Krizai commented Feb 9, 2017

Implemented custom possibility to use custom setter with error out parameter

It allows to use another JSONModel initializers inside custom setter and propagate error to the topmost. Like here:


- (void)setIconsWithNSDictionary:(NSDictionary *)dictionary error:(NSError**) error
{
    NSMutableDictionary* icons = [NSMutableDictionary new];
    __block NSError* blockError = nil;
    [dictionary enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
        NSError* localError = nil;
        PFEffectImageJS* effectImage = [[PFEffectImageJS alloc] initWithDictionary:obj error:&localError];
        if(localError){
            blockError = localError;
            *stop = YES;
            return;
        }
        icons[key] = effectImage;
    }];
    
    if(error){
        *error = blockError;
    }

    self.icons = icons;
}

@billinghamj
Copy link
Member

Ah excellent! :) I have been wanting this for a while - much cleaner than the previous solution. Will review and probably make a couple of tweaks.

@ghost ghost mentioned this pull request Feb 14, 2017
Copy link
Member

@billinghamj billinghamj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, have reviewed in detail. Most of the changes are stylistic to fit in with the newer code in the project (I know much of the older code is quite different).

Finally, please add tests for both the old and new use of the setters (with BOOL and void return types), add something to show that the old method is deprecated, and update the readme please

if ([self __customSetValue:jsonValue forProperty:property]) {
NSError* customSetErr = nil;
if ([self __customSetValue:jsonValue forProperty:property error:&customSetErr]) {
if((err != nil) && (customSetErr != nil))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please update to:

if (err != nil && customSetErr != nil)
  *err = customSetErr;

@@ -327,7 +328,12 @@ -(BOOL)__importDictionary:(NSDictionary*)dict withKeyMapper:(JSONKeyMapper*)keyM

// check for custom setter, than the model doesn't need to do any guessing
// how to read the property's value from JSON
if ([self __customSetValue:jsonValue forProperty:property]) {
NSError* customSetErr = nil;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please change to NSError *customSetErr

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you use any formatter tool to take care of formatting. Something like uncrustify?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately not at present, no

-(void)__addCustomSetterForName:(NSString*) name
withSuffix:(NSString*) suffix
key:(NSString*) key
toProperty:(JSONModelClassProperty*) p{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please change to something more like:

- (void)__addCustomSetterToProperty:(JSONModelClassProperty *)property withValueType:(NSString *)valueType
{
  • all args/params on a single line
  • curly brace on a new line
  • space before pointer asterisks, rather than after
  • no space before variable names
  • more clear variable/param naming
  • avoiding unneeded params

p.customSetters[key] = [[JSONModelCustomSetter alloc] initWithValue:setterValue withErrorOutParam:NO];
}

SEL setterWithError = NSSelectorFromString([NSString stringWithFormat:@"set%@With%@:error:", name, suffix]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check for the error setter first, then return within the respondsToSelector conditional block

@@ -841,22 +861,30 @@ -(id)__reverseTransform:(id)value forProperty:(JSONModelClassProperty*)property
}

#pragma mark - custom transformations
- (BOOL)__customSetValue:(id <NSObject>)value forProperty:(JSONModelClassProperty *)property
- (BOOL)__customSetValue:(id <NSObject>)value forProperty:(JSONModelClassProperty *)property error:(NSError**) error
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Space before pointer asterisks


if ([self respondsToSelector:setterWithError]){
NSValue* setterValue = [NSValue valueWithBytes:&setterWithError objCType:@encode(SEL)];
p.customSetters[key] = [[JSONModelCustomSetter alloc] initWithValue:setterValue withErrorOutParam:YES];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Init with SEL object directly, not the NSValue

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(NSValue was only used because an NSDictionary cannot hold a value type - e.g. SEL, thus there is no need to use NSValue at all)

return NO;

SEL setter = nil;
[customSetter.value getValue:&setter];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull SEL directly from JSONModelCustomSetter property, rather than using an NSValue


@interface JSONModelCustomSetter : NSObject

@property ( nonatomic, readonly, strong) NSValue* value;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change to SEL type

@property ( nonatomic, readonly, strong) NSValue* value;
@property ( nonatomic, readonly, assign) BOOL withErrorOutParam;

- (instancetype)initWithValue:(NSValue*)value withErrorOutParam:(BOOL) withErrorOutParam;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change to:

- (instancetype)initWithSelector:(SEL)selector;

Determine the presence of the error param based on the selector - don't pass this in

if (p.customSetters[key])
return;

SEL setter = NSSelectorFromString([NSString stringWithFormat:@"set%@With%@:", name, suffix]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please move all this logic into JSONModelCustomSetter - probably something like:

JSONModelCustomSetter *setter = [JSONModelCustomSetter setterForObj:self propertyName:name valueType:suffix];

if (setter)
  p.customSetters[key] = setter;

Copy link
Author

@Krizai Krizai Feb 24, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From my point of view, anyway, I should first check, does the selector exist, and only then create JSONModelCustomSetter. So I can only hide into the class the magic of wrapping into the NSValue ( which anyway will be removed)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the selector doesn't exist, setterForObj would return nil.

@billinghamj
Copy link
Member

Also needs to be rebased

@Krizai
Copy link
Author

Krizai commented Feb 25, 2017

Do you think old method should be deprecated? I would leave both of them, as in many cases there is no need for error processing in custom setter.

@Krizai
Copy link
Author

Krizai commented Feb 25, 2017

Please check new update

@billinghamj
Copy link
Member

Yes the old method should be deprecated - we avoid supporting more than one way of doing a given thing at once generally, as it keeps it more maintainable.

@Krizai
Copy link
Author

Krizai commented May 6, 2017

Added the warning about deprecation of the old method

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

Successfully merging this pull request may close these issues.

None yet

2 participants