Re: tearing my hair, ok here is a compilable example.
Re: tearing my hair, ok here is a compilable example.
- Subject: Re: tearing my hair, ok here is a compilable example.
- From: "Stephen J. Butler" <email@hidden>
- Date: Thu, 16 Oct 2008 02:03:25 -0500
It has something to do with Class1 being a subclass of
NSObjectController. This code works for me with the same IB
connections (sorry, had to reformat; it's my compulsion):
#import <Cocoa/Cocoa.h>
@interface Class1 : NSObject
{
BOOL canLink;
}
- (BOOL) canLink;
- (IBAction) change:(id)v;
@end
#import "Class1.h"
@implementation Class1
- (BOOL) canLink
{
NSLog( @"%s %d nc:%p", _cmd, canLink, self );
return canLink;
}
- (IBAction) change:(id)v
{
[self willChangeValueForKey:@"canLink"];
canLink = !canLink;
[self didChangeValueForKey:@"canLink"];
NSLog( @"%s %d", _cmd, canLink );
}
- (void) setCanLink:(BOOL)aValue
{
canLink = aValue;
}
@end
#import <Cocoa/Cocoa.h>
@class Class1;
@interface Class2 : NSObject
{
IBOutlet Class1 *class1;
}
- (BOOL) myMethod;
@end
#import "Class2.h"
#import "Class1.h"
@implementation Class2
+ (NSSet*) keyPathsForValuesAffectingMyMethod
{
NSLog( @"%s", _cmd );
return [NSSet setWithObject:@"class1.canLink"];
}
#pragma mark -
- (void) awakeFromNib
{
NSLog( @"%s class1:%p", _cmd, class1 );
[self addObserver:self
forKeyPath:@"myMethod"
options:NSKeyValueObservingOptionNew
context:[Class2 class]];
}
- (void) observeValueForKeyPath:(NSString*)keyPath
ofObject:(id)object
change:(NSDictionary*)change
context:(void *)context
{
NSLog( @"%s %@", _cmd, keyPath );
if (context == [Class2 class])
{
if ([keyPath isEqualToString:@"myMethod"])
{
NSLog( @"newvalue - myMethod:%d", [self myMethod] );
}
}
else
{
[super observeValueForKeyPath:keyPath ofObject:object
change:change context:context];
}
}
- (BOOL) myMethod
{
return [class1 canLink];
}
@end
On Thu, Oct 16, 2008 at 1:18 AM, Chris Idou <email@hidden> wrote:
> That thought had occured to me, but making it readwrite doesn't seem to help. Cocoa NIB loading doesn't seem to call accessors, it seems to access them more directly. I even tried this:
>
>
> -(Class1 *)class1 {
> return class1;
> }
>
> -(void)setClass1:(Class1 *)v {
> NSLog(@"setClass1: %@", v);
> [self willChangeValueForKey:@"class1"];
> class1 = v;
> [self didChangeValueForKey:@"class1"];
> }
>
> But they don't get called.
>
> I even tried adding to awakeFromNIB:
>
> id old = [self class1];
> [self setClass1:nil];
> [self setClass1:old];
>
> To try and force the issue, but to no avail.
>
> Someone has observed that my code works when called from main() and bypassing IB. But it still doesn't work when loaded from a NIB!
>
>
> --- On Wed, 10/15/08, Quincey Morris <email@hidden> wrote:
>
>> From: Quincey Morris <email@hidden>
>> Subject: Re: tearing my hair, ok here is a compilable example.
>> To: email@hidden
>> Date: Wednesday, October 15, 2008, 10:54 PM
>> On Oct 15, 2008, at 22:13, Chris Idou wrote:
>>
>> > @class Class1;
>> > @interface Class2 : NSObject {
>> > IBOutlet Class1 *class1;
>> >
>> >
>> > }
>> > @property(readonly) Class1 *class1;
>> > -(BOOL)myMethod;
>> > @end
>> >
>> > #import "Class2.h"
>> > #import "Class1.h"
>> >
>> > @implementation Class2
>> >
>> > @synthesize class1;
>> >
>> > ...
>> >
>> > - (void)awakeFromNib {
>> > [self addObserver:self
>> > forKeyPath:@"myMethod"
>> > options:NSKeyValueObservingOptionNew
>> > context: [Class2 class]];
>> >
>> > }
>> >
>> >
>> > + (NSSet *)keyPathsForValuesAffectingMyMethod {
>> >
>> NSLog(@"keyPathsForValuesAffectingMyMethod");
>> > return [NSSet
>> setWithObject:@"class1.canLink"];
>> > }
>>
>> I think your problem is that Class2 isn't properly KVO
>> compliant for
>> the key "class1". Consider what happens when your
>> nib is loaded. At
>> some point, the nib loader needs to set "class1"
>> to its correct value.
>> Since the property is readonly and synthesized, there's
>> no setter
>> method, so the instance variable is changed directly.
>> (I'm going from
>> memory here, but I believe that's what documented to
>> happen.) That
>> presumably fails to trigger any KVO notifications, and your
>>
>> "keyPathsForValuesAffectingMyMethod" is not
>> consulted.
>>
>> Try this:
>>
>> > ...
>>
>> > @interface Class2 ()
>>
>> > @property(readwrite) Class1 *class1;
>> > @end
>>
>> >
>>
>> > @implementation Class2
>> >
>> > @synthesize class1;
>> > ....
>>
>> If my theory is correct, that should cause the outlet to be
>> set via a
>> KVC-compliant setter, and the keypath dependency should
>> start working.
>>
>>
>> _______________________________________________
>>
>> 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
>
>
>
> _______________________________________________
>
> 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
>
_______________________________________________
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