Challenge 1


#1

Hi I had tried to make the challenge 1 : sort with the length, but I’ve failed.
I read that it is possible to make it only with the Interface Builder, so I open my project and launch my : “MyDocument.xib” file.
I select the Table Column and go to Attributes in the Inspector.
From now I’ve tried many ideas :

  • 1st : I thought “length” was an operator so I put @length.personName for “Sort Key” and use compare: as “Selector”
  • 2ndly : I use @count.personName as “Sort Key” and compare: as “Selector”
  • 3rd : I use employees.@count.personName as “Sort Key” and compare as “Selector”

My conclusions :
Thanks to GDB I understood that @length isn’t an operator so I’ve stopped using it.
I think my problem is with my Key-path, may be I don’t completely understand how it works.
But my major issue is “How do I use length methode of NSString?”

I use the code that I’ve made earlier in the chapter with an NSSarrayController.
MyDocument.h

[code]#import <Cocoa/Cocoa.h>
@interface MyDocument : NSDocument
{
NSMutableArray *employees;
}

  • (void)setEmployees:(NSMutableArray *)a;
    @end[/code]

MyDocument.m

[code]#import “MyDocument.h”
@implementation MyDocument

  • (id)init
    {
    self = [super init];
    if (self)
    {
    employees = [[NSMutableArray alloc] init];
    }
    return self;
    }

  • (void)dealloc
    {
    [self setEmployees:nil];
    [super dealloc];
    }

  • (void)setEmployees:(NSMutableArray *)a
    {
    if (a==employees)
    {
    return;
    }
    else
    {
    [a retain];
    [employees release];
    employees = a;
    }
    }

  • (NSString *)windowNibName
    {
    return @“MyDocument”;
    }

  • (void)windowControllerDidLoadNib:(NSWindowController *) aController
    {
    [super windowControllerDidLoadNib:aController];
    }

  • (NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError
    {
    if ( outError != NULL ) {
    *outError = [NSError errorWithDomain:NSOSStatusErrorDomain code:unimpErr userInfo:NULL];
    }
    return nil;
    }

  • (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError
    {
    if ( outError != NULL ) {
    *outError = [NSError errorWithDomain:NSOSStatusErrorDomain code:unimpErr userInfo:NULL];
    }
    return YES;
    }

@end
[/code]

Person.h

#import <Foundation/Foundation.h> @interface Person : NSObject { NSString *personName; float expectedRaise; } @property(readwrite,copy) NSString *personName; @property(readonly) float expectedRaise; @end

Person.m

[code]#import “Person.h”
@implementation Person

  • (id)init
    {
    [super init];
    expectedRaise = 5.0;
    personName = @“New Person”;
    return self;
    }

  • (void)dealloc
    {
    [personName release];
    [super dealloc];
    }

@synthesize personName;
@synthesize expectedRaise;

@end
[/code]


#2

When I first tried to solve this challenge, I got a bit confused since the hint reminded me that NSString objects have a length method that could be called but the key value binding appeared to apply to properties and not methods. How to get the length method to be called? Earlier in chapter 7, Aaron mentions that the accessor methods will be used to read/write an instance variable if they exist for the class but their names must meet accessor naming convention (setFido: and fido for example if the instance variable was named fido.) This would mean that if you tried to retrieve the length property through key-value coding, it would send a message to the ‘length’ method if it existed for the class, thinking that it was the get accessor for this property. This gets us the call to the length method we want.

If you look the “For the More Curious: Key Paths” section in chapter 7 (page 120 in my 3rd edition), it will show how a key value path can be used to access a nested instance variable such as “spouse.scooter.modelName”.

If you put these two together, you should be able to specify the correct key path in the ‘Sort Key’ field of the column in IB. compare: should do the trick for the Selector as you mentioned in your e-mail.

Hope that helps