Search code examples
objective-ccocoacocoa-bindingskey-value-observing

Updating Bound NSTextField When Child Object Changes


I am having trouble with a NSTextField (or potentially any NSControl) updating it's visible properties when the object's child object it is bound to changes.

I think code would simplify the understanding of the problem (simplified for this example):

// Team object contains a team leader of object type MyPerson

@interface MyTeam : NSObject {

   MyPerson * teamLeader;
   NSString * teamName;
}

@property (readwrite, retain) MyPerson * teamLeader;
@property (readwrite, copy) NSString * teamName;

-(NSString *)teamLeaderFirstName;
-(NSString *)teamLeaderLastName;

// In the implementation file return the first name and last name
// of the teamLeader

@implementation MyTeam

@synthesize teamLeader
@synthesize teamName;

-(NSString *)teamLeaderFirstName {
    return [[self teamLeader] teamLeaderFirstName;
}

-(NSString *)teamLeaderLastName {
    return [[self teamLeader] teamLeaderLastName;
}

Bindings are:

NSArrayController --> NSArray of MyTeam objects
NSTableView --> NSArrayController
NSTextField --> NSArrayController --> Selected Item --> Team Name
NSTextField --> NSArrayController --> Selected Item --> Lead First Name
NSTextField --> NSArrayController --> Selected Item --> Lead Last Name

When I select a team in the table, a call goes out to a web server to fetch the team information and the child objects (including the team lead) are updated appropriately. However, the team lead first and last name are not updated in the UI until I select another team and then come back to the first team selected.

I know what's happening, the bound text fields are not being notified of the changes to the MyPerson object. What I don't know is how to make the MyPerson object KVC/KVO compliant for this purpose.

I have tried forcing using willChangeValueForKey and didChangeValueForKey. Despite the fact this didn't work for me, I think that's the wrong way of doing it.

I have tried binding directly to the object instead of using an intermediary method (the teamLeadFirstName getter), but that didn't work either. I know the data is being populated in the model on the call from the server because I can confirm it in the debugger. So my issue I believe is just the KVO portion.

Target is 10.6 only so no legacy issues involved.

Any help or suggestions on how to resolve this would be very much appreciated.


Solution

  • Stupid mistake on my part. I was binding to a class method that was not KVO compliant in the child object.

    Stupid, stupid mistake.