Re: How can an instance KVO its own and super's attributes, especially with overrides?
Re: How can an instance KVO its own and super's attributes, especially with overrides?
- Subject: Re: How can an instance KVO its own and super's attributes, especially with overrides?
- From: Ken Thomases <email@hidden>
- Date: Wed, 20 Aug 2014 23:46:52 -0500
On Aug 20, 2014, at 11:02 PM, Daryle Walker <email@hidden> wrote:
> I’m writing an NSOperation subclass. Instances are dumped into the main queue, but I hope I stop them from executing right away by overriding -isReady. But the docs say I have to keep the override KVO-compliant. And my formula for the new -isReady uses the old one. Can I observe on super?
"super" refers to the same object as "self". There's no separate thing to observe.
"super" is not a pointer to an object, actually. It's only valid as a receiver of a message invocation and the only thing it does is modify the dispatch of that message. It modifies how the runtime searches for a method implementation for that message. In particular, the search starts with the methods implemented by the superclass of the code into which the super keyword was compiled, skipping over any methods supplied by the current class and any subclasses.
(More specifically, a message to super translates into a call to one of the objc_msgSendSuper*() functions rather than objc_msgSend*(). But the specified receiver is the same exact pointer. For objc_msgSendSuper*(), the receiver is passed indirectly in a struct, but, still, it's the same object pointer.)
It follows that super doesn't have separate attributes from self. If the superclass modifies one of its attributes, it's modifying the object's attributes, period. If it does so in a KVO-compliant manner, it will emit KVO change notifications. This is indistinguishable to observers from when your subclass modifies them.
>> + (NSSet *)keyPathsForValuesAffectingIsReady {
>> return [NSSet setWithObjects:@"super.isReady", @"cancelledFiles", @"failedFiles", @"successfulFiles", nil];
>> }
"super" is not a key – it doesn't name a property – so it has no place in a key path. It also makes no sense. This is saying the isReady property depends on the isReady property. (Remember, there's no separate object. super is just a reference to self.)
So, you need to drop the "super.isReady" pseudo-key-path.
However, there's a problem with your method. If a superclass implements +keyPathsForValuesAffectingIsReady or +keyPathsForValuesAffectingValueForKey: which checks for @"isReady", then you would mask that and break stuff.
You might be tempted to fix that by invoking [super keyPathsForValuesAffectingIsReady], but you can't be sure that the superclass used that form of the method.
Then, you might be tempted to invoke [super keyPathsForValuesAffectingValueForKey:@"isReady"]. The problem there is that a superclass may have implemented +keyPathsForValuesAffectingIsReady. In that case, it will be relying on the NSObject implementation of +keyPathsForValuesAffectingValueForKey: turning around and invoking +keyPathsForValuesAffectingIsReady for that key. But how would NSObject's implementation invoke that? It will send it to self (the class object, since these are class methods). But that will invoke your implementation again. You'll get infinite recursion.
So, I think the only safe approach when you're overriding a property is to override +keyPathsForValuesAffectingValueForKey: and not +keyPathsForValuesAffectingIsReady. In your override, you pass through to super. Then, you check if the key is @"isReady" and, if it is, add your key paths.
>> - (BOOL)isReady {
>> return [super isReady] && (self.cancelledFiles.count + self.failedFiles.count + self.successfulFiles.count >= files.count);
>> }
> Are my key paths for my own attributes correct?
Yes.
> Can I point to an attribute from super with “super.whatever”?
No and it's not necessary. If the superclass changes what its implementation of -isReady returns, then it must emit KVO change notifications since it promised in its design contract that that property is KVO-compliant. Those change notifications reach the same observers and have the same meaning as ones you would emit yourself.
> Can I really trigger my ready flag with just indirect observations on the four attributes I need?
Yes. You don't show any mutation of the "files" property. I'm assuming it is set during initialization and never changes after that. If that's correct, then it's KVO-compliant and you're good.
Regards,
Ken
_______________________________________________
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