Re: Bindings validation for NSMutableArray of NSMutableDictionary
Re: Bindings validation for NSMutableArray of NSMutableDictionary
- Subject: Re: Bindings validation for NSMutableArray of NSMutableDictionary
- From: Mike Abdullah <email@hidden>
- Date: Fri, 14 Dec 2012 11:13:25 +0000
I'd strongly advise the OP it's better for them to create a custom class for their model objects, rather than go down this route of globally modifying NSMutableDictionary's API.
On 13 Dec 2012, at 22:18, email@hidden wrote:
> On 13 Dec 2012, at 11:54, email@hidden wrote:
>
>> I bind an NSArray of NSMutableDictionary instances to an NSTableView and enable NSTableColumn editing..
>>
>> How can I best implement KVO based validation when editing the view?
>>
>> Subclassing NSArray controller is a no go as validateValue:forKeyPath:error is never called.
>> Subclassing the NSMutableDictionary model obviously isn't desirable.
>>
>> I can refactor the NSMutableDictionary instances into custom objects and use model based validation if needed.
>>
>> However, binding dictionaries into table views is often convenient so a working validation strategy would be useful.
>>
>> Jonathan
>
> The following category enables NSMutableDictionary KVC validation routing to a delegate.
>
> NSMutableDictionary *connection = [self selectedConnection];
> connection.validationDelegate = self;
>
> The delegate then performs validation in:
>
> - (BOOL)validateValue:(id *)ioValue forKey:(NSString *)key error:(NSError **)outError sender:(NSMutableDictionary *)sender
>
> See https://github.com/mugginsoft/NSMutableDictionary-KVCValidation
>
> Simple refactoring would enable routing of KVC validation for any class.
>
> Jonathan
>
>
> #import "NSMutableDictionary+KVCValidation.h"
> #import <objc/runtime.h>
>
> const char validationDelegateKey;
>
> /*
>
> MethodSwizzle()
>
> ref: http://www.mikeash.com/pyblog/friday-qa-2010-01-29-method-replacement-for-fun-and-profit.html
>
> */
> void MethodSwizzle(Class klass, SEL origSEL, SEL overrideSEL)
> {
> Method origMethod = class_getInstanceMethod(klass, origSEL);
> Method overrideMethod = class_getInstanceMethod(klass, overrideSEL);
>
> // try and add instance method with original selector that points to new implementation
> if (class_addMethod(klass, origSEL, method_getImplementation(overrideMethod), method_getTypeEncoding(overrideMethod))) {
>
> // add or replace method so that new selector points to original method
> class_replaceMethod(klass, overrideSEL, method_getImplementation(origMethod), method_getTypeEncoding(origMethod));
> } else {
>
> // class already has an override method so just swap the implementations.
> method_exchangeImplementations(origMethod, overrideMethod);
> }
> }
>
> @implementation NSMutableDictionary (KVCValidation)
>
> /*
>
> + load
>
> */
> + (void)load
> {
> MethodSwizzle(self, @selector(validateValue:forKey:error:), @selector(swizzle_validateValue:forKey:error:));
> }
>
> /*
>
> - setValidationDelegate:
>
> */
> - (void)setValidationDelegate:(id)validationDelegate
> {
> objc_setAssociatedObject(self, &validationDelegateKey, validationDelegate, OBJC_ASSOCIATION_RETAIN);
> }
>
> /*
>
> - validationDelegate
>
> */
> - (id)validationDelegate
> {
> return objc_getAssociatedObject(self, &validationDelegateKey);
> }
>
> /*
>
> - swizzle_validateValue:forKey:error:
>
> */
> - (BOOL)swizzle_validateValue:(id *)ioValue forKey:(NSString *)key error:(NSError **)outError
> {
> id validationDelegate = self.validationDelegate;
> SEL validationSelector = @selector(validateValue:forKey:error:sender:);
> BOOL isValid = NO;
>
> if ([validationDelegate respondsToSelector:validationSelector]) {
> isValid = [validationDelegate validateValue:ioValue forKey:key error:outError sender:self];
> } else {
> // remember, we swap IMPS at run time
> isValid = [self swizzle_validateValue:ioValue forKey:key error:outError];
> }
>
> return isValid;
> }
> @end
>
> Jonathan
>
>
> _______________________________________________
>
> Cocoa-dev mailing list (email@hidden)
>
> Please do not post admin requests or moderator comments to the list.
> Contact the moderators at cocoa-dev-admins(at)lists.apple.com
>
> Help/Unsubscribe/Update your Subscription:
>
> This email sent to email@hidden
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden