Cocoa and Objective-C: Up and Running (by me) is now available from O'Reilly.

NSArray and KVC

Even more on simplifying code with generic programming! NSArray's -valueForKey: has a feature that may not be immediately obvious. You can use it to return an array of values buried within a tree of objects. Here's a working example:


NSMutableArray * tree = [NSMutableArray array];

NSDictionary   * p = nil;   // parent
NSDictionary   * c = nil;   // child    
NSNumber       * n = nil;   // value

int i;
for ( i = 0; i < 10; i++ )
{
  n = [NSNumber numberWithInt: i];

  c = [NSDictionary dictionaryWithObject: n
                                  forKey: @"someKey"];

  p = [NSDictionary dictionaryWithObject: c
                                  forKey: @"storage"];

  [tree addObject: p];
}


NSLog (@"%@", tree);


// here's the important part!

NSArray * justValues;
justValues = [tree valueForKeyPath: @"storage.someKey"];


NSLog (@"%@", justValues);




The first NSLog spits this out -- just a two-level property list:


NSLog (@"%@", tree);



(
    {storage = {someKey = 0; }; },
    {storage = {someKey = 1; }; },
    {storage = {someKey = 2; }; },
    {storage = {someKey = 3; }; },
    {storage = {someKey = 4; }; },
    {storage = {someKey = 5; }; },
    {storage = {someKey = 6; }; },
    {storage = {someKey = 7; }; },
    {storage = {someKey = 8; }; },
    {storage = {someKey = 9; }; }
)



The second NSLog spits out an array of values collected by asking each contained object for the value at @"storage.someKey":


NSArray * justValues;
justValues = [tree valueForKeyPath: @"storage.someKey"];

NSLog (@"%@", justValues);



(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)



I find this really convenient in Core Data when working with a sorted array of  managed objects -- you can pull out an array of values for just one attribute.
Design Element
NSArray and KVC
Posted Oct 04, 2005 — 4 comments below




 

Abhi Beckert — Oct 12, 05 431

*ching*

Now I finally understand how the binding key for a table column works! Thanks ;)

Dirk — Mar 09, 06 923

Unfortunately, I do not. I tried to show the results in "justvalues" in a TableView column using bindings. I use an ArrayController whose content outlet is connected to an instance of the class. The column of the TableView is bound to the ArrayController, controller key is arranged objects, model key path is tree.storage.someKey.
This does not work unfortunately. If I switch to another application, the TableView will eventually show the (0, 1, 2, 3, 4, 5, 6, 7, 8, 9) - but in just one row! :-(
I am looking for an really easy example to this since - well, very long. I've gone through a lot of them on the web - but since I am very new to cocoa, I found them to complicated. Maybe you could give some hints? Thanks in advance and greetings ;-)

Bagelturf — Mar 24, 07 3807

Dirk,

Try my ten-part KVC tutorial at:

http://www.bagelturf.com/cocoa/kvc1/kvc1.html

It is *very* simple and includes downloadable projects for each step. I did it to convince myself that I understood KVC.

(The links to the download page in the text are incorrect. Use the one from the menu on the right.)

Ben — May 20, 09 6778

Can i extend this to traverse a sequence of KVC items e.g. first.second.third.fourth

Also can this mechanism just deal with to-one relationships or is there a way to make it link to an array and then follow into the items returned by the array items.




 

Comments Temporarily Disabled

I had to temporarily disable comments due to spam. I'll re-enable them soon.




Technorati Profile
Copyright © Scott Stevenson 2004-2008