Re: KVO query

2014-08-14 Thread Jonathan Mitchell

On 13 Aug 2014, at 23:41, Quincey Morris quinceymor...@rivergatesoftware.com 
wrote:

 On Aug 13, 2014, at 14:53 , Jonathan Mitchell jonat...@mugginsoft.com wrote:
 
 At one point i need to invoke a manual KVO notification like so:
 
 [submission willChangeValueForKey:@“status”];
 [submission didChangeValueForKey:@“status”];
 
 This raises like so:
 
 Terminating app due to uncaught exception 
 'NSInternalInconsistencyException', reason: 'Cannot update for observer 
 NSKeyValueObservance 0x608000ac21b0 for the key path status.name from 
 Submission 0x6080003aa800, most likely because the value for the key 
 status has changed without an appropriate KVO notification being sent. 
 Check the KVO-compliance of the Submission class.’
 
 This is one of those infuriating errors that is hard to make sense of. Try 
 thinking about it literally.
 
 Because you’re observing the “status.name” path from ‘submission’, the 
 observer is *also* observing the “name” path from ‘submission.status’**. In 
 your scenario, the originally observed ‘status’ instance (call it X) is no 
 longer the current ‘status’ instance at willChange time (it’s now Y, say), 
 and in general it might not be the same as that at didChange time (Z, say). 
 Even if Y == Z, there’s been a non-KVO-compliant change in ‘status’ prior to 
 the notification being sent.
 
 Now, we do this quite often, without problems, but I’d suggest that’s only in 
 cases where the “temporarily non KVO compliant” change is for the *last* key 
 of the path — in which case the last object isn’t being observed, just 
 because it’s the last key.

This is where I am getting caught out. As you say it works fine for the last 
key of the path. It does for me too.

I am effectively propagating a C# PropertyChanged event. This approach by 
itself will never be KVO compliant and will fail when mutating non last 
components in an observed key path.
 
 So, in the case of a non-KVO-compliant change to the value of a non-terminal 
 key path object, the non-KVO-compliance may not be tolerated by the 
 frameworks. Hence this error message.
 
 What I suggest you try is to make two properties: “currentStatus” and 
 “observableStatus”. The second of these would be updated KVO compliantly 
 (i.e. via its setter) when you know that the first has changed and the change 
 should be propagated (i.e. in the places where you now trigger the 
 willChange/didChange notification manually). Code in the ‘submission’ class 
 can use ‘self.currentStatus’ to get or set the most recent status object; 
 observers would observe “observableStatus”, of course.
Using a proxy property sounds like it might be doable.

Thanks

Jonathan
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: KVO query

2014-08-14 Thread Jonathan Mitchell

On 13 Aug 2014, at 23:40, Ken Thomases k...@codeweavers.com wrote:

 
 You have to issue the -willChange… _before_ the property has changed.  That's 
 because that's KVO's only opportunity to get the value that's about to become 
 old and remove its observations for the properties of that old object.
 
 So, that pattern of issuing -willChange… followed immediately by -didChange… 
 with nothing actually changing in between is a sure sign of a problem.
 
 The solution is annoying but relatively simple.  You need to hold a strong 
 reference to the old object in a property of your own.  So, you need a 
 property status that is _not_ just a pass-through to some other API.  It 
 needs to be backed by an instance variable (e.g. _status) that is a strong 
 reference to the object.  Then, when you receive the notification from the 
 underlying API that something has changed, you fetch the new object from that 
 API and assign it to self.status.  That assignment is KVO-compliant.  You 
 can/should then eliminate your manual -will/didChange… invocations.
 

That all makes sense.

I am effectively just propagating the C# PropertyChanged event. This is 
fundamentally not KVO compliant.
C# also provides a PropertyChanging event, though it is not so commonly 
implemented.

For managed event changes to be KVO compliant in managed code I will have to 
ensure that the managed layer events are sent in a may that is KVO compliant 
when they emerge in unmanaged code.

Thanks

Jonathan


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

KVO query

2014-08-13 Thread Jonathan Mitchell
I have a key path like so which is observed:

submission.status.name

At one point i need to invoke a manual KVO notification like so:

[submission willChangeValueForKey:@“status”];
[submission didChangeValueForKey:@“status”];

This raises like so:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', 
reason: 'Cannot update for observer NSKeyValueObservance 0x608000ac21b0 for 
the key path status.name from Submission 0x6080003aa800, most likely 
because the value for the key status has changed without an appropriate KVO 
notification being sent. Check the KVO-compliance of the Submission class.’

I am using manual KVO because my submission object is a wrapper around a Mono 
managed class.
I receive a callback that the managed status object has changed and want to 
propagate that via KVO.
The true situation is generic : i receive a callback that a managed property P 
has changed and want to raise manual KVO notifications in a compliant manner.

Is there a way for me to programatically determine what sequence of manual  KVO 
notifications  I will require to maintain KVO compliance?
I imagine that the framework code uses - observationInfo to achieve this but 
that is opaque to client code.
I am trying to avoid having lots of explicit 
+keyPathsForValuesAffectingValueForKey: methods.

Thanks

Jonathan












___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: KVO query

2014-08-13 Thread Lee Ann Rucker
Have you implemented +automaticallyNotifiesObserversForKey: and returned NO for 
“status” ?

On Aug 13, 2014, at 2:53 PM, Jonathan Mitchell jonat...@mugginsoft.com wrote:

 I have a key path like so which is observed:
 
 submission.status.name
 
 At one point i need to invoke a manual KVO notification like so:
 
 [submission willChangeValueForKey:@“status”];
 [submission didChangeValueForKey:@“status”];
 
 This raises like so:
 
 Terminating app due to uncaught exception 'NSInternalInconsistencyException', 
 reason: 'Cannot update for observer NSKeyValueObservance 0x608000ac21b0 for 
 the key path status.name from Submission 0x6080003aa800, most likely 
 because the value for the key status has changed without an appropriate KVO 
 notification being sent. Check the KVO-compliance of the Submission class.’
 
 I am using manual KVO because my submission object is a wrapper around a Mono 
 managed class.
 I receive a callback that the managed status object has changed and want to 
 propagate that via KVO.
 The true situation is generic : i receive a callback that a managed property 
 P has changed and want to raise manual KVO notifications in a compliant 
 manner.
 
 Is there a way for me to programatically determine what sequence of manual  
 KVO notifications  I will require to maintain KVO compliance?
 I imagine that the framework code uses - observationInfo to achieve this but 
 that is opaque to client code.
 I am trying to avoid having lots of explicit 
 +keyPathsForValuesAffectingValueForKey: methods.
 
 Thanks
 
 Jonathan


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: KVO query

2014-08-13 Thread Ken Thomases

On Aug 13, 2014, at 4:53 PM, Jonathan Mitchell jonat...@mugginsoft.com wrote:

 I have a key path like so which is observed:
 
 submission.status.name
 
 At one point i need to invoke a manual KVO notification like so:
 
 [submission willChangeValueForKey:@“status”];
 [submission didChangeValueForKey:@“status”];
 
 This raises like so:
 
 Terminating app due to uncaught exception 'NSInternalInconsistencyException', 
 reason: 'Cannot update for observer NSKeyValueObservance 0x608000ac21b0 for 
 the key path status.name from Submission 0x6080003aa800, most likely 
 because the value for the key status has changed without an appropriate KVO 
 notification being sent. Check the KVO-compliance of the Submission class.’
 
 I am using manual KVO because my submission object is a wrapper around a Mono 
 managed class.
 I receive a callback that the managed status object has changed and want to 
 propagate that via KVO.
 The true situation is generic : i receive a callback that a managed property 
 P has changed and want to raise manual KVO notifications in a compliant 
 manner.
 
 Is there a way for me to programatically determine what sequence of manual  
 KVO notifications  I will require to maintain KVO compliance?

You have to issue the -willChange… _before_ the property has changed.  That's 
because that's KVO's only opportunity to get the value that's about to become 
old and remove its observations for the properties of that old object.

So, that pattern of issuing -willChange… followed immediately by -didChange… 
with nothing actually changing in between is a sure sign of a problem.

The solution is annoying but relatively simple.  You need to hold a strong 
reference to the old object in a property of your own.  So, you need a property 
status that is _not_ just a pass-through to some other API.  It needs to be 
backed by an instance variable (e.g. _status) that is a strong reference to the 
object.  Then, when you receive the notification from the underlying API that 
something has changed, you fetch the new object from that API and assign it to 
self.status.  That assignment is KVO-compliant.  You can/should then eliminate 
your manual -will/didChange… invocations.

Regards,
Ken


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: KVO query

2014-08-13 Thread Quincey Morris
On Aug 13, 2014, at 14:53 , Jonathan Mitchell jonat...@mugginsoft.com wrote:

 At one point i need to invoke a manual KVO notification like so:
 
 [submission willChangeValueForKey:@“status”];
 [submission didChangeValueForKey:@“status”];
 
 This raises like so:
 
 Terminating app due to uncaught exception 'NSInternalInconsistencyException', 
 reason: 'Cannot update for observer NSKeyValueObservance 0x608000ac21b0 for 
 the key path status.name from Submission 0x6080003aa800, most likely 
 because the value for the key status has changed without an appropriate KVO 
 notification being sent. Check the KVO-compliance of the Submission class.’

This is one of those infuriating errors that is hard to make sense of. Try 
thinking about it literally.

Because you’re observing the “status.name” path from ‘submission’, the observer 
is *also* observing the “name” path from ‘submission.status’**. In your 
scenario, the originally observed ‘status’ instance (call it X) is no longer 
the current ‘status’ instance at willChange time (it’s now Y, say), and in 
general it might not be the same as that at didChange time (Z, say). Even if Y 
== Z, there’s been a non-KVO-compliant change in ‘status’ prior to the 
notification being sent.

Now, we do this quite often, without problems, but I’d suggest that’s only in 
cases where the “temporarily non KVO compliant” change is for the *last* key of 
the path — in which case the last object isn’t being observed, just because 
it’s the last key.

So, in the case of a non-KVO-compliant change to the value of a non-terminal 
key path object, the non-KVO-compliance may not be tolerated by the frameworks. 
Hence this error message.

What I suggest you try is to make two properties: “currentStatus” and 
“observableStatus”. The second of these would be updated KVO compliantly (i.e. 
via its setter) when you know that the first has changed and the change should 
be propagated (i.e. in the places where you now trigger the 
willChange/didChange notification manually). Code in the ‘submission’ class can 
use ‘self.currentStatus’ to get or set the most recent status object; observers 
would observe “observableStatus”, of course.



** Because there’re “really” no such thing as a key path observation. It’s 
“really” a chain of object/key observations.

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com