On Jun 26, 2008, at 6:54 PM, Stuart Malin wrote:

I am trying to gain a working understanding of KVC. I have made a small app that has a class Party which has a property "attendees" that holds Person objects. The attendees property is KVC compliant for a mutable array (it has index accessors). In another part of my app, I want to find the Nth attendee. My first approach to doing so was to code: Person *person = [[party mutableArrayValueForKey:@"attendees"] objectAtIndex:index]; This does work, and, as I best understand, it complies with the KVC protocol. But I do believe this approach generates a proxy mutable array, which seems inefficient to me.

Since you say below that you have an -attendees method, why not

        Person *person = [[party attendees] objectAtIndex:index];

?

As the underlying Party class is KVC compliant for the attendees property, I substituted the above with:
        Person *person = [party objectInAttendeesAtIndex:index];
This does work. But I sense I may be breaking some sort of "encapsulation" regarding the workings of KVC by using the accessors that support it.

Doesn't seem like breaking encapsulation to me. Your code is still always the gatekeeper of access to the property, so it's still encapsulated. Just as much as it is to provide an -attendees method, for example. In theory, it offers greater encapsulation since your code could, if you wanted, make decisions about how to behave on an element-by-element basis, which isn't possible if you give up the array all at once.

The compiler issued a warning that "Party" may not respond to - objectInAttendeesAtIndex: because I hadn't included the index accessors in the class's header file... Which I could do.... But then wonder even more if I am exposing something that I shouldn't. Question: is it acceptable (perhaps even desirable) to expose the index accessors of a class via its interface declaration (header file)?

Yes.

I've said this before -- so much so that I probably sound like a broken record: the property is not the ivar. The ivar, if it exists at all, is an implementation detail for the property. The property is the set of methods in the class interface which allow clients to inquire about that information/state of your object. Therefore, it is perfectly sensible, and often very much the right thing to do, to put the KVC accessors in the interface of your class.

One example is when your to-many property is not backed by an array. Suppose the objects in the to-many relationship are pulled from a database. Or generated on demand, or whatever. Maybe your property is backed by a library which only provides an interface for counting and access-by-index (e.g. CGImageSource). Maybe your property represents a large but sparse array. A property might not actually have a -<key> accessor (because it would be prohibitively expensive to generate the required array); it might _only_ exist as the set of indexed accessors. In that case, as you can imagine, clients could only use those KVC accessors to access the property, and they'd be perfectly "right" to do so.


Also: I could add a method to my Party class to provide such access in a way that seems more semantically direct, to wit: -personAtIndex: Would providing such a method be preferred to having code elsewhere in the app use the Party class's KVC index accessor(s)?
(It does seem quite redundant)

It seems redundant to me, too. (To be pedantic, it would more appropriately be -attendeeAtIndex:. ;)

Seems like a matter of personal taste/style. Give it a try and see if it feels more (or less) comfortable or efficient or whatever-criterion- matters-to-you. I doubt you'll be excoriated here for either choice.


Separately, I have an accessor -attendees: of the Party class, which is currently implemented as:

- (NSArray*) attendees
{
return [NSArray arrayWithArray:attendees]; // "attendees" is an NSMutableArray, and is an ivar
}

I intentionally do not return the underlying mutable array, because I don't want other code accessing the content without going through the accessors.

Is my implementation reasonable? Or are there preferable ways to do this (such as to return a copy of the mutable array)?

My personal theory is that using -copy (plus -autorelease) at least gives the opportunity for a more efficient implementation. In this case, there's probably no point, but in the general case my rule is to go with the most semantically specific operation to give the implementation the greatest amount of information and thus the greatest opportunity to do something "smart".

That said, the larger issue is whether to protect yourself against your clients. We just had a fairly good thread on this subject: <http://lists.apple.com/archives/Cocoa-dev/2008/Jun/msg00188.html >.

Lastly, just let me say you're doing very well for a self-described "noob"! :)

Cheers,
Ken
_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]

Reply via email to