Re: How to implement an object whose properties are really dictionary entries.
Re: How to implement an object whose properties are really dictionary entries.
- Subject: Re: How to implement an object whose properties are really dictionary entries.
- From: Keary Suska <email@hidden>
- Date: Thu, 12 Jul 2012 08:05:28 -0600
On Jul 12, 2012, at 3:32 AM, Motti Shneor wrote:
> Thanks Quincey. I seem to have missed that one.
Yes, Quincy is right. I was forgetting about the dot syntax issue as I haven't been using it much for my implementation. Note, however, that if you plan to use bindings with these objects you will have to also implement the kind of approach we discussed.
> I already have dealt with forwardInvocation, in another class (some kind of NSNotificationCenter replacement which dispatches messages to registered objects, in prioritized and synchronized way). I think I can do it without much hassle. This covers things like [myObject firstName] in addition to myObject.firstName, and [myObject setFirstName] in addition to myObject.firstName = @"xxx";
The bit I forgot is that dot syntax is really syntactic sugar--all the compiler does with it is compile the statement as if it was actually written using a method call. I.e., [myObject firstName] is exactly the same operation as myObject.firstName.
> I do not intend to forward the invocation at all, rather to parse it, and call my internal general-purpose setter/getter method.
>
> I completely forgot about "respondsToSelecor:" but here, again, it can be done --- only I hate to implement cocoa's naming convention myself (knowing I have a key like "firstName", to respond to a @selector(setFirstName:). Isn't the machinery for that part of the runtime? Who implements those naming conventions?
You can handle the invocation any way you want, including ignoring it entirely. You shouldn't need to override respondsToSelector: as Quincy pondered, if you also implement the undefined key approach. If you don't, then you might have to.
The forwardInvocation implementation would be easy. In theory, all you need to distinguish is the setX vs X pattern, determine the actual key name (really just extracting and formatting when you get a setX method), change the selector of the invocation to the appropriate undefined key method, and invoke it.
HTH,
Keary Suska
Esoteritech, Inc.
"Demystifying technology for your home or business"
> On 12 ביול 2012, at 10:59, Quincey Morris wrote:
>
>> On Jul 12, 2012, at 00:14 , Motti Shneor wrote:
>>
>>> On 12 ביול 2012, at 02:54, Keary Suska wrote:
>>>
>>>> On Jul 11, 2012, at 2:45 PM, Motti Shneor wrote:
>>>>> Of what I read from everyone, and after examining the suggested code from Jens Alfke, I think I'm inclined to something simpler, hinted by Keary Suska. Could you spare a few more words on the "undefinedKey" override?
>>>>
>>>> I would create a base class that implements -valueForUndefinedKey: and -setValue:forUndefinedKey: (per the doc links that another poster provided). These methods would simply get/set from the dictionary. The only thing that requires a little consideration is how you may choose to validate the key (if at all)--i.e. determine whether you want to throw an exception for unknown keys. You can throw by simply calling super's implementation. To validate you could keep an array of valid key names (somewhat fragile, as you need to keep it updated), or use runtime inspection functions (see:https://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtPropertyIntrospection.html#//apple_ref/doc/uid/TP40008048-CH101-SW24). More cryptic but not fragile.
>>>>
>>>
>>> Thanks, I think this is exactly what I was looking for.
>>>
>>> In my case it is almost trivial. These classes maintain dictionaries to convert from the class' Keys (properties) to the base-model (CoreData) attribute names in the schema. I can simply look up the internal key, and throw (via super implementation of valueForUndefinedKey/setValue:forUndefinedKey) if I can't find it.
>>>
>>> If I'm going this route, do I still need to use the @dynamic for my properties? after all --- promised implementations wont be available in runtime. I rely on a KVO pre-exception mechanism.
>>
>> Maybe I haven't been following this closely enough, but you and Keary seem to be talking at cross purposes.
>>
>> -- If you *do* want to call property accessors in clients of your class, then the KVC method such as 'valueForUndefinedKey:' are of no use to you, because the accessors don't go through KVC. (It's the other way round -- KVC will call the accessors if they exist.)
>>
>> In this case, I think you should take a look at 'forwardInvocation:', documented here:
>>
>> https://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtForwarding.html#//apple_ref/doc/uid/TP40008048-CH105-SW1
>>
>> Note that you can't actually forward the invocation as is, since there's no implementation of the relevant methods anywhere, but notice the comment that "A forwardInvocation: method can act as a distribution center for unrecognized messages, … . It can translate one message into another, …". In other words, you'll have to detect/validate the selector/parameter pattern in the invocation, then modify or recreate the invocation to refer to a pair of methods that do the actual work. None of this should be very hard, since there are only 2 selector patterns to detect.
>>
>> This technique would avoid mucking about with the runtime class information directly (which you seem reluctant to do).
>>
>> The only issues I see are:
>>
>> a. I think you'll need to override 'respondsToSelector:' as well as 'forwardInvocation:', so that KVC will think that your dynamic accessors exist.
>>
>> b. This all depends on knowing whether property names are valid, but you say that you know that without having to add any data structures to your class implementation. You'll just have to define the properties as '@dynamic' to keep the compiler from complaining.
>>
>> If you're not willing (or able, for some reason I haven't foreseen) to use an approach like this, I think Dave's suggestion of macros is your best solution, although it's a little bit ugly at the source code level.
>>
>> -- If you *don't* want to call property accessors in clients of your class, but use the class only for (e.g.) bindings or other things that use KVC, then 'valueForUndefinedKey:' etc. is the right way to go.
_______________________________________________
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