Re: KVO - deallocation with observers attached

2017-06-02 Thread Jonathan Mitchell

> On 1 Jun 2017, at 00:51, Ken Thomases <k...@codeweavers.com> wrote:
> 
> On May 31, 2017, at 5:02 PM, Jonathan Mitchell <li...@mugginsoft.com> wrote:
>> 
>> It is common for deallocating objects to abort if they have observers still 
>> registered.
>> 
>> The Data_Test object is deallocated with non nil -observationInfo and yet it 
>> does not abort.
>> Why does this occur?
> 
> It's not clear to me that the KVO machinery is obligated to set 
> observationInfo to nil when an object is no longer being observed.  Note that 
> observationInfo is *not* an object pointer.  It's a pointer to void.  Among 
> other things, that means that there's no memory management involved in the 
> setter.  That is, it's not a strong reference or even a weak one.  So, for 
> example, it's not necessary for KVO to nil it out to free memory.

Thanks for the input.
I wasn’t able to get to the bottom of this despite poking around with Hopper 
through the foundation framework.
There is an NSKVODeallocate foundation function that can get called when an 
observed object gets deallocated.
It raises the familiar KVO exception if -observationInfo is not nil.

- observationInfo does return a void* but it dereferences to an 
NSKeyValueObservationInfo :  NSObject instance.
Its obviously private API though.

I was able to track the comings and goings of NSKeyValueObservationInfo using 
the memory graph debugger and malloc stack logging but enlightenment did not 
strike.

I was able to make my test project behave as I anticipated but my real world 
app doesn’t seem so compliant.

I am just trying to eradicate the possibility of crashes that occur when the 
observing object deallocs and the observed object keeps pumping notifications 
to the old observers address.

Thanks

J

___

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 - deallocation with observers attached

2017-05-31 Thread Ken Thomases
On May 31, 2017, at 5:02 PM, Jonathan Mitchell <li...@mugginsoft.com> wrote:
> 
> It is common for deallocating objects to abort if they have observers still 
> registered.
> 
> However in some cases it seems that an object can get deallocated with 
> observers attached and not abort.
> 
> I have instrumented my test case thoroughly and overridden 
> -setObservationInfo: to log the observation changes as below.
> 
> The Data_Test object is deallocated with non nil -observationInfo and yet it 
> does not abort.
> Why does this occur?

It's not clear to me that the KVO machinery is obligated to set observationInfo 
to nil when an object is no longer being observed.  Note that observationInfo 
is *not* an object pointer.  It's a pointer to void.  Among other things, that 
means that there's no memory management involved in the setter.  That is, it's 
not a strong reference or even a weak one.  So, for example, it's not necessary 
for KVO to nil it out to free memory.

That also means that you should not be logging the observationInfo as though it 
were an object (using the "%@" format specifier or otherwise sending the 
-description message to it).  As mentioned in the observationInfo docs, 
"Overrides of this property must not attempt to send messages to the stored 
data."

By the way, does your override just log and call through to super?  Or did you 
actually implement storage in an instance variable?  If you did the latter, 
it's conceivable that you changed whether or not crashes are likely to follow 
deallocation with observers.  That's because the observationInfo would not be 
stored in a global look-aside table such that it could get accidentally 
attached to an unrelated object that happened to be allocated at the same 
address.

> I am sorting through some observer related crash reports just trying to 
> figure out possible causes.

I would think you'd have better luck logging the addition and removal of 
observers looking for an imbalance.

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


KVO - deallocation with observers attached

2017-05-31 Thread Jonathan Mitchell
It is common for deallocating objects to abort if they have observers still 
registered.

However in some cases it seems that an object can get deallocated with 
observers attached and not abort.

I have instrumented my test case thoroughly and overridden -setObservationInfo: 
to log the observation changes as below.

The Data_Test object is deallocated with non nil -observationInfo and yet it 
does not abort.
Why does this occur?

I am sorting through some observer related crash reports just trying to figure 
out possible causes.

The Data_Test object is heavily observed throughout its lifetime both by 
bindings and explicit observations.

macOS 10.12

2017-05-31 22:49:01.616632+0100 MyApp Data_Test (0x11336d100) SetObservationInfo
2017-05-31 22:49:01.616656+0100 MyApp oldObservationInfo : 
 (
 Context: 0x10075a4b8, Property: 
0x6144abc0>
 
Context: 0x0, Property: 0x608000a51280>
)
2017-05-31 22:49:01.616692+0100 MyApp newObservationInfo : 
 (
 Context: 0x10075a4b8, Property: 
0x6144abc0>
)
2017-05-31 22:49:04.188226+0100 MyApp Data_Test (0x11336d100) dealloc

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: Translating KVO-ed property to Swift

2017-04-24 Thread Charles Srstka
> On Apr 24, 2017, at 1:17 PM, Quincey Morris 
> <quinceymor...@rivergatesoftware.com> wrote:
> 
> On Apr 24, 2017, at 10:11 , Charles Srstka <cocoa...@charlessoft.com 
> <mailto:cocoa...@charlessoft.com>> wrote:
>> 
>> What Quincey seemed to be referring to was a property that was not backed by 
>> any kind of persistent value.
> 
> That wasn’t actually the kind of property I had in mind. I was thinking of 
> settable, computed properties that did not depend on the value(s) of other 
> KVO-observable properties. There probably aren’t many plausible *simple* 
> examples, but I was thinking of such cases as when the value is stored in an 
> I/O device rather than RAM, or when the value is retrieved from a server.

In this case, I would try to see if I could find some way to monitor changes in 
the underlying storage, and call the willChange and didChange methods manually 
when changes occur. I’d only make the property dynamic if it was completely 
impossible to do this, and I’d keep this to a last resort. The reason is 
because in this case, the property is not fully KVO-compliant, because its 
value can change without notifications being sent.

I did kind of touch on this with the UserDefaults-example I provided a while 
back. Pretending that NSUserDefaults still notified via NSNotifications only, 
as was the case before native KVO support was added to it, you would register 
for the NSNotification, check whether your default had changed, and fire the 
willSet and didSet notifications once it did. This is a lot more robust than 
depending on the automatic notifications when your property’s value may change 
without going through the property’s setter.

Charles

___

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: Translating KVO-ed property to Swift

2017-04-24 Thread Quincey Morris
On Apr 24, 2017, at 10:11 , Charles Srstka <cocoa...@charlessoft.com> wrote:
> 
> What Quincey seemed to be referring to was a property that was not backed by 
> any kind of persistent value.

That wasn’t actually the kind of property I had in mind. I was thinking of 
settable, computed properties that did not depend on the value(s) of other 
KVO-observable properties. There probably aren’t many plausible *simple* 
examples, but I was thinking of such cases as when the value is stored in an 
I/O device rather than RAM, or when the value is retrieved from a server.

One problem with such examples, though, is that it’s not clear in the abstract 
whether you would keep a stored (RAM) value as well. Another problem I’ve been 
brooding over is whether a property (stored or computed) that has KVO 
dependencies can actually be regarded as a dependent property *if it has a 
setter*. Depending on the details, I suspect, the property could be regarded as 
fully dependent, partially dependent, not dependent, or not classifiable.

Separately, I’ve been brooding over the kinds of audiences that might need 
advice (advisories) about using “dynamic”. I think there’s a large fraction of 
the developer population, perhaps a majority, who aren’t aware of the details 
of how KVO notifications are implemented, and an explanation is just a 
distraction that’s more confusing than enlightening. (For any one developer, 
that can change over time, of course.)

This makes me think that there need to be two rules, one simple and one 
advanced, for two different audiences.

The simple rule applies when you allow Cocoa to generate KVO notifications 
automatically (when setters are called or when you use 
“keyPathsForValuesAffecting”), but in deference to Charles’ concerns isn’t 
quite as simple as what the documentation says. It’s now this:

> Add the “dynamic” keyword if the property has a setter.


This covers the cases where “dynamic” is absolutely required (independent 
properties), and it covers all dependent properties without a setter (which, in 
practice, is most of them). It *might* add an unnecessary “dynamic” to a 
computed property with a setter, but I really think it’s the safest solution in 
such cases.

The advanced rule goes something like this:

> For any property with a setter, if you generate notifications manually via 
> willSet/didSet, and you don’t need or want automatic notifications produced 
> by the setter, you must implement “automaticallyNotifiesObserversOf” to 
> return ‘false’, and the property doesn’t need the “dynamic” keyword. 
> Otherwise, add “dynamic” if there is a setter.


That is (I hope/intend) exactly equivalent to what Charles has being saying.

___

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: Translating KVO-ed property to Swift

2017-04-24 Thread Charles Srstka
> On Apr 24, 2017, at 10:07 AM, Richard Charles <rcharles...@gmail.com> wrote:
> 
>> 
>> On Apr 23, 2017, at 11:27 AM, Charles Srstka <cocoa...@charlessoft.com 
>> <mailto:cocoa...@charlessoft.com>> wrote:
>> 
>>> On Apr 20, 2017, at 3:06 PM, Quincey Morris 
>>> <quinceymor...@rivergatesoftware.com 
>>> <mailto:quinceymor...@rivergatesoftware.com>> wrote:
>>> 
>>> Where I disagree is in your much stronger claim that a computed property is 
>>> *necessarily* a dependent property. I think this is just false. The Swift 
>>> distinction between computed and stored properties is syntactic and has 
>>> nothing to do with KVO**. A KVO-observed computed property should 
>>> therefore, according to the documented principle, be marked “dynamic”. For 
>>> anyone following your extended principle, if it’s also a dependent 
>>> property, they can omit the “dynamic”. If not, not.
>> 
>> Do you have any example of a property not backed by anything where KVO even 
>> makes sense? The whole purpose of KVO is to watch changes to values, and if 
>> there’s no value, it seems like the wrong tool.
> 
> I have a property that returns an array. A setter for this property makes no 
> sense. The property returns a collection of managed objects that is the 
> composite value of several to-many relationships.
> 
> This property is KVO compliant and bound to the NSContentArrayBinding of an 
> array controller.
> 
> There is most likely more than one way to do this but I find using bindings 
> convienient. You can bind to a KVO compliant property. You can't bind to a 
> notification.
> 
> This is in an Objective-C project that requires interoperability with a C++ 
> library. So using Swift is not possible but maybe someday it will be.
> 
> --Richard Charles

But it sounds like this property *is* backed by a value. The backing is the 
collection of managed objects. I take it you’re simply watching changes to the 
C++ source data and calling didChange/willChange when appropriate—basically 
translating one type of notification to another. This makes perfect 
sense—although not having a setter, being marked ‘dynamic’ would not change its 
behavior at all.

What Quincey seemed to be referring to was a property that was not backed by 
any kind of persistent value. Presumably, this property would also have a 
setter, since otherwise ‘dynamic’ isn’t really in play. I’m very curious as to 
what the applicability of such a thing would be, because I can’t think of any 
myself.

Charles

___

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: Translating KVO-ed property to Swift

2017-04-24 Thread Richard Charles

> On Apr 23, 2017, at 11:27 AM, Charles Srstka <cocoa...@charlessoft.com> wrote:
> 
>> On Apr 20, 2017, at 3:06 PM, Quincey Morris 
>> <quinceymor...@rivergatesoftware.com> wrote:
>> 
>> Where I disagree is in your much stronger claim that a computed property is 
>> *necessarily* a dependent property. I think this is just false. The Swift 
>> distinction between computed and stored properties is syntactic and has 
>> nothing to do with KVO**. A KVO-observed computed property should therefore, 
>> according to the documented principle, be marked “dynamic”. For anyone 
>> following your extended principle, if it’s also a dependent property, they 
>> can omit the “dynamic”. If not, not.
> 
> Do you have any example of a property not backed by anything where KVO even 
> makes sense? The whole purpose of KVO is to watch changes to values, and if 
> there’s no value, it seems like the wrong tool.

I have a property that returns an array. A setter for this property makes no 
sense. The property returns a collection of managed objects that is the 
composite value of several to-many relationships.

This property is KVO compliant and bound to the NSContentArrayBinding of an 
array controller.

There is most likely more than one way to do this but I find using bindings 
convienient. You can bind to a KVO compliant property. You can't bind to a 
notification.

This is in an Objective-C project that requires interoperability with a C++ 
library. So using Swift is not possible but maybe someday it will be.

--Richard Charles

___

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: Translating KVO-ed property to Swift

2017-04-23 Thread Charles Srstka
Sorry I didn’t get around to replying sooner; I’ve had a busy past few days.

> On Apr 20, 2017, at 3:06 PM, Quincey Morris 
> <quinceymor...@rivergatesoftware.com> wrote:
> 
> On Apr 20, 2017, at 10:24 , Charles Srstka <cocoa...@charlessoft.com 
> <mailto:cocoa...@charlessoft.com>> wrote:
>> 
>> I mean, yes, we could go all the way down to explaining how everything works 
>> in terms of the physics and chemistry of electrons and semiconductors, but 
>> that wouldn’t be very practical, would it?
> 
> I subscribe to the principle already quoted from the documentation: If you 
> KVO-observe a property, mark it “dynamic”. I like this because it is simple 
> and unambiguous. If anyone asked me for advice, I’d say to follow this 
> principle and don’t agonize any further.

It is simple, and it’ll work, and there’s certainly nothing wrong with it. It’s 
a little non-ideal performance-wise, though, which is why I prefer using 
dynamic only where it’s needed.

> As a different discussion, at a different level, I agree that there are 
> scenarios where you can omit “dynamic” and still get all the KVO 
> notifications you wanted. What scenarios? Well, I think the essence of your 
> argument is that it can be omitted for a KVO-observed *dependent* property.

The essence of my argument is pretty simple; it can be omitted for any property 
where willChange and didChange are already being called.

For a dependent property, those calls will be made in your dependency, so you 
don’t need dynamic. For a stored property where you’re calling willChange and 
didChange yourself, you don’t need dynamic. For, I dunno, weird situations 
where willChange and didChange are getting called somewhere else but at the 
appropriate times, you don’t need dynamic. Dynamic is only needed to let Cocoa 
add the willChange and didChange notifications for you.

> That at least sounds pretty plausible to me, and it may even be true by 
> definition. If anyone asked you for advice, then I guess you’d say to accept 
> this as an extension of the documented principle. Me, I’m not 100% certain 
> about this, if for no other reason than the documented principle is 
> future-proof against a change in the way things work where Apple says, “Well, 
> we told to you mark all KVO-observed properties dynamic.” But, people can go 
> for advice where they want.

This isn’t just based on empirical observation, though; it’s based on the 
documentation of the KVO mechanism, which predates Swift by quite a lot. KVO 
isn’t a mysterious black box; the details of it are all available in the 
documentation, and once you understand them, you understand *why* dynamic is 
needed. And once you understand *why* it’s needed, you also will understand 
*where* it’s needed. Personally, I prefer to, when possible, understand the 
reasons behind doing things rather than repeating magical incantations.

As for future-proof, I fully expect that in some future version of Swift (Swift 
5, hopefully, maybe Swift 6), we’ll get a new and improved, Swift-native 
replacement for KVC and KVO and we’ll all be ripping out our existing KVO code 
in favor of that anyway.

> Where I disagree is in your much stronger claim that a computed property is 
> *necessarily* a dependent property. I think this is just false. The Swift 
> distinction between computed and stored properties is syntactic and has 
> nothing to do with KVO**. A KVO-observed computed property should therefore, 
> according to the documented principle, be marked “dynamic”. For anyone 
> following your extended principle, if it’s also a dependent property, they 
> can omit the “dynamic”. If not, not.

Do you have any example of a property not backed by anything where KVO even 
makes sense? The whole purpose of KVO is to watch changes to values, and if 
there’s no value, it seems like the wrong tool.

I mean, sure, I could make this observable:

var whyWouldIObserveThis: Int {
return Int(arc4random())
}

and then send didChange/willChange notifications on a timer or something. 
But... *why?*

Charles

___

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: Translating KVO-ed property to Swift

2017-04-20 Thread Jean-Daniel
Just a tough that go in the ‘always use dynamic’ side. I think setter 
interposition is not the only issue with KVO. KVO also need to be able to fetch 
the old property value when -willChange: is called. I’m not sure about how it 
does that, but I’m pretty confident it will break if the getter is not properly 
exposed in Obj-C, which may be the case if the property is neither declare 
@objc, nor dynamic.

> Le 20 avr. 2017 à 22:06, Quincey Morris <quinceymor...@rivergatesoftware.com> 
> a écrit :
> 
> On Apr 20, 2017, at 10:24 , Charles Srstka <cocoa...@charlessoft.com> wrote:
>> 
>> I mean, yes, we could go all the way down to explaining how everything works 
>> in terms of the physics and chemistry of electrons and semiconductors, but 
>> that wouldn’t be very practical, would it?
> 
> I subscribe to the principle already quoted from the documentation: If you 
> KVO-observe a property, mark it “dynamic”. I like this because it is simple 
> and unambiguous. If anyone asked me for advice, I’d say to follow this 
> principle and don’t agonize any further.
> 
> As a different discussion, at a different level, I agree that there are 
> scenarios where you can omit “dynamic” and still get all the KVO 
> notifications you wanted. What scenarios? Well, I think the essence of your 
> argument is that it can be omitted for a KVO-observed *dependent* property. 
> That at least sounds pretty plausible to me, and it may even be true by 
> definition. If anyone asked you for advice, then I guess you’d say to accept 
> this as an extension of the documented principle. Me, I’m not 100% certain 
> about this, if for no other reason than the documented principle is 
> future-proof against a change in the way things work where Apple says, “Well, 
> we told to you mark all KVO-observed properties dynamic.” But, people can go 
> for advice where they want.
> 
> Where I disagree is in your much stronger claim that a computed property is 
> *necessarily* a dependent property. I think this is just false. The Swift 
> distinction between computed and stored properties is syntactic and has 
> nothing to do with KVO**. A KVO-observed computed property should therefore, 
> according to the documented principle, be marked “dynamic”. For anyone 
> following your extended principle, if it’s also a dependent property, they 
> can omit the “dynamic”. If not, not.
> 
> 
> ** Indeed, it’s trivially easy to convert a public stored property into a 
> public computed property that uses a private, stored, non-KVO-observed 
> property as its instance storage.
> 
> ___
> 
> 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/mailing%40xenonium.com
> 
> This email sent to mail...@xenonium.com

___

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: Translating KVO-ed property to Swift

2017-04-20 Thread Quincey Morris
On Apr 20, 2017, at 10:24 , Charles Srstka <cocoa...@charlessoft.com> wrote:
> 
> I mean, yes, we could go all the way down to explaining how everything works 
> in terms of the physics and chemistry of electrons and semiconductors, but 
> that wouldn’t be very practical, would it?

I subscribe to the principle already quoted from the documentation: If you 
KVO-observe a property, mark it “dynamic”. I like this because it is simple and 
unambiguous. If anyone asked me for advice, I’d say to follow this principle 
and don’t agonize any further.

As a different discussion, at a different level, I agree that there are 
scenarios where you can omit “dynamic” and still get all the KVO notifications 
you wanted. What scenarios? Well, I think the essence of your argument is that 
it can be omitted for a KVO-observed *dependent* property. That at least sounds 
pretty plausible to me, and it may even be true by definition. If anyone asked 
you for advice, then I guess you’d say to accept this as an extension of the 
documented principle. Me, I’m not 100% certain about this, if for no other 
reason than the documented principle is future-proof against a change in the 
way things work where Apple says, “Well, we told to you mark all KVO-observed 
properties dynamic.” But, people can go for advice where they want.

Where I disagree is in your much stronger claim that a computed property is 
*necessarily* a dependent property. I think this is just false. The Swift 
distinction between computed and stored properties is syntactic and has nothing 
to do with KVO**. A KVO-observed computed property should therefore, according 
to the documented principle, be marked “dynamic”. For anyone following your 
extended principle, if it’s also a dependent property, they can omit the 
“dynamic”. If not, not.


** Indeed, it’s trivially easy to convert a public stored property into a 
public computed property that uses a private, stored, non-KVO-observed property 
as its instance storage.

___

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: Translating KVO-ed property to Swift

2017-04-20 Thread Charles Srstka
> On Apr 19, 2017, at 9:12 PM, Quincey Morris 
> <quinceymor...@rivergatesoftware.com> wrote:
> 
> On Apr 19, 2017, at 15:49 , Charles Srstka <cocoa...@charlessoft.com> wrote:
>> 
>> Cocoa automagically does its secret subclass thing to wrap the setter and 
>> call the didChange/willChange calls for any property you didn’t tell it not 
>> to do. It needs the property to be dynamic for this to work. 
> 
> Yes, that’s almost exactly what I said**. But it still doesn’t make the 
> “dynamic” keyword an on/off switch. Again, the KVO notifications aren’t 
> activated *because* the method has the Swift-specific dynamic attribute, but 
> because the method uses Obj-C dispatching. The “dynamic” keyword [currently] 
> forces the method to use Obj-C dispatching, but the reverse isn’t true. In 
> the absence of the keyword, there’s nothing formally stopping the compiler 
> from using Obj-C dispatching if it chooses to.
> 
> At some level, though, I’m prepared to stipulate that it’s a distinction 
> without much practical difference.

The statement didn’t say anything about “dynamic” being an “on/off switch.” The 
statement that you were quibbling was that you can mark a stored property as 
‘dynamic’, and Cocoa will do the rest. It didn’t say anything about what 
*causes* it, it was meant to be a practical guide to how to implement KVO 
properties in Swift. And to make Cocoa automatically handle the 
didChange/willChange calls, you mark a property as dynamic. I mean, yes, we 
could go all the way down to explaining how everything works in terms of the 
physics and chemistry of electrons and semiconductors, but that wouldn’t be 
very practical, would it?

>> I should add that if a computed property needs ‘dynamic’ in order for its 
>> notifications to fire, the property is not properly KVO-compliant.
> 
> It’s impossible to say in general what counts as a change to a mutable 
> property. Indeed it’s perfectly possible for a property to exist for the 
> purpose of generating KVO notifications without having any meaningful value, 
> and there are plenty more un-generalizable considerations:

The entire purpose of KVO is to monitor changes to values. The word “value” is 
literally right there in the title, as well as most of the major APIs that make 
it work. observeValue. willChangeValue. didChangeValue. value(forKey:). 
setValue. keyPathsForValuesAffecting. Using KVO without a meaningful value is, 
frankly, using a hammer to drive in a screw. For a value-less notification, 
something like NSNotificationCenter is a much better choice.

> — It’s up to an individual property (with a meaningful value) to decide 
> whether KVO notifications are issued when the setter is called (in effect, 
> the default case) or when the value actually changes (as in Rick’s original 
> code), or under some other conditions (e.g. I can imagine a property limiting 
> the rate of notifications using a timer).

Which does not require a property to be dynamic, and in fact would require 
*disabling* Cocoa’s use of dynamism for the property, via returning false for 
automaticallyNotifiesObserversOf.

> — There’s no general presumption whether the value returned by the getter is 
> synchronized with the value passed to the setter.

The setter, however, is likely to make some kind of change to the underlying 
storage such that we will be notified of it. And if no such change is made, 
then there is little point in sending change notifications.

> — There’s no general presumption whether the value returned by the getter is 
> synchronized with the notification, in a multi-threaded environment.

Assuming you’re referring to the fact that something in another thread could 
change the property in the middle of your observer, this still has little that 
I can see to do with the ‘dynamic’ keyword.

> — There’s no general presumption that KVO notifications originate in the 
> property's setter at all, or in the setter only.
> 
> Etc. “keyPathsForValuesAffecting…”-style dependencies are just a convenient 
> short-cut to a specific, simple, typical behavior.

Who said there was?

The bottom line with KVO notifications is that you’ll get one when either:
1. willChange and didChange get called for the property you’re 
watching, or
2. willChange and didChange get called for something that the property 
you’re watching is dependent on.

In case 1, you can either call willChange or didChange yourself, or you can let 
Cocoa do it for you. In Swift, you need to mark it ‘dynamic’ for the latter to 
happen.

In case 2, you don’t need willChange or didChange to get called for your 
property, because we will already get notified when the dependency’s willChange 
and didChange get called. In fact, we might not want them to, because it’ll 
cause the notification to double-post—once in the setter, and 

Re: Translating KVO-ed property to Swift

2017-04-19 Thread Quincey Morris
On Apr 19, 2017, at 15:49 , Charles Srstka <cocoa...@charlessoft.com> wrote:
> 
> Cocoa automagically does its secret subclass thing to wrap the setter and 
> call the didChange/willChange calls for any property you didn’t tell it not 
> to do. It needs the property to be dynamic for this to work. 

Yes, that’s almost exactly what I said**. But it still doesn’t make the 
“dynamic” keyword an on/off switch. Again, the KVO notifications aren’t 
activated *because* the method has the Swift-specific dynamic attribute, but 
because the method uses Obj-C dispatching. The “dynamic” keyword [currently] 
forces the method to use Obj-C dispatching, but the reverse isn’t true. In the 
absence of the keyword, there’s nothing formally stopping the compiler from 
using Obj-C dispatching if it chooses to.

At some level, though, I’m prepared to stipulate that it’s a distinction 
without much practical difference.

> I should add that if a computed property needs ‘dynamic’ in order for its 
> notifications to fire, the property is not properly KVO-compliant.

It’s impossible to say in general what counts as a change to a mutable 
property. Indeed it’s perfectly possible for a property to exist for the 
purpose of generating KVO notifications without having any meaningful value, 
and there are plenty more un-generalizable considerations:

— It’s up to an individual property (with a meaningful value) to decide whether 
KVO notifications are issued when the setter is called (in effect, the default 
case) or when the value actually changes (as in Rick’s original code), or under 
some other conditions (e.g. I can imagine a property limiting the rate of 
notifications using a timer).

— There’s no general presumption whether the value returned by the getter is 
synchronized with the value passed to the setter.

— There’s no general presumption whether the value returned by the getter is 
synchronized with the notification, in a multi-threaded environment.

— There’s no general presumption that KVO notifications originate in the 
property's setter at all, or in the setter only.

Etc. “keyPathsForValuesAffecting…”-style dependencies are just a convenient 
short-cut to a specific, simple, typical behavior.



** Incidentally, when I was testing in Swift, I didn’t see any indication the 
backtrace that a subclass was being used, or that any actual swizzling was 
being done. It looked more like the dynamic dispatch was diverted to a 
general-purpose function that generated the notifications around the actual 
setter invocation. Here’s a partial backtrace when a breakpoint in the 
“version” didSet accessor was hit:

frame #0: 0x0001190b 
TestKVO`ViewController.version.willset(newValue="1", self=0x618000100900) 
at ViewController.swift:16
frame #1: 0x00011877 
TestKVO`ViewController.version.setter(newValue="1", self=0x618000100900) at 
ViewController.swift:0
frame #2: 0x000117d8 TestKVO`@objc ViewController.version.setter at 
ViewController.swift:0
frame #3: 0x7fff91d6c897 
Foundation`-[NSObject(NSKeyValueObservingPrivate) 
_changeValueForKeys:count:maybeOldValuesDict:usingBlock:] + 848
frame #4: 0x7fff91bf1c7d 
Foundation`-[NSObject(NSKeyValueObservingPrivate) 
_changeValueForKey:key:key:usingBlock:] + 60
frame #5: 0x7fff91c5a55b Foundation`_NSSetObjectValueAndNotify + 261
frame #6: 0x0001310f 
TestKVO`ViewController.buttonClicked(sender=some, self=0x618000100900) -> 
() at ViewController.swift:57
frame #7: 0x00013200 TestKVO`@objc 
ViewController.buttonClicked(Any?) -> () at ViewController.swift:0
frame #8: 0x7fffa5b903a7 
libsystem_trace.dylib`_os_activity_initiate_impl + 53
frame #9: 0x7fff8e475791 AppKit`-[NSApplication(NSResponder) 
sendAction:to:from:] + 456

and here is a disassembly of the Swift code (frame 6) that invokes the setter:

0x130f2 <+434>: movq   0x3ebf(%rip), %rsi; "setVersion:"
0x130f9 <+441>: movq   %rax, %rcx
0x130fc <+444>: movq   -0x20(%rbp), %rdx
0x13100 <+448>: movq   %rdx, %rdi
0x13103 <+451>: movq   %rcx, %rdx
0x13106 <+454>: movq   %rax, -0x80(%rbp)
0x1310a <+458>: callq  0x147d2   ; symbol stub for: 
objc_msgSend

That is, the objc_msgSend ended up in the Foundation function 
_NSSetObjectValueAndNotify. I traced through the objc_msgSend, and it goes 
straight to _NSSetObjectValueAndNotify from the method dispatch tables.

Just an interesting sidelight to this discussion. In the old days, you could 
definitely see the secret subclass if you looked.

___

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 Subsc

Re: Translating KVO-ed property to Swift

2017-04-19 Thread Charles Srstka
> On Apr 19, 2017, at 4:50 PM, Quincey Morris 
> <quinceymor...@rivergatesoftware.com> wrote:
> 
>> 3. Computed properties do not need to be dynamic, […].
> 
> This is also not exactly true. Computed properties that have only a getter do 
> not need to be dynamic, because they don’t generate any KVO notifications via 
> a setter, and so “dynamic” is irrelevant.
> 
> However, a computed property that has a setter will *not* produce the 
> expected notifications unless it is marked “dynamic”, even if marked “@objc”. 
> (I tested this to be sure.) There’s nothing special about computed vs. stored 
> properties in this regard.

I should add that if a computed property needs ‘dynamic’ in order for its 
notifications to fire, the property is not properly KVO-compliant. There are 
three ways this could happen that I can think of off the top of my head:

Case #1: Derived from another KVO property

> @objc dynamic var foo: String
> 
> @objc var bar: String {
>   get { return self.foo }
>   set { self.foo = newValue }
> }

The above will not fire notifications for bar. Making bar ‘dynamic’ appears to 
fix the problem, but it is in fact still not compliant; if foo changes, bar’s 
value is changed as well, but its notifications will not fire. The proper way 
to fix this is to add keyPathsForValuesAffectingBar.

Case #2: Backed by something not exposed to Objective-C

> enum Option: String {
>   case foo = “Foo"
>   case bar = “Bar"
>   case baz = “Baz"
> }
> 
> var option: Option
> 
> @objc var objcOption: String {
>   get { return self.option.rawValue }
>   set {
>   if let option = Option(rawValue: newValue) {
>   self.option = option
>   }
>   }
> }

The above will not fire notifications for objcOption. Making objcOption 
‘dynamic’ appears to fix the problem, but if option is changed, objcOptions’s 
value will change as well, and its notifications will not fire. The proper way 
to fix this is to add willChangeValue(forKey:) and didChangeValue(forKey:) 
calls in option’s willSet and didSet accessors.

Case #3: It’s backed by something other than a property

> @objc var isFoo: Bool {
>   get { return UserDefaults.bool(forKey: “Foo”) }
>   set { UserDefaults.set(newValue, forKey: “Foo”) }
> }

The above will not fire notifications for isFoo. Making isFoo ‘dynamic’ appears 
to fix the problem, but if the “Foo” defaults key changes by some mechanism 
other than isFoo’s setter, isFoo’s value will have changed, but the 
notifications will not fire. The better solution is to register for changes on 
UserDefaults or NSUserDefaultsController via one of the several available 
mechanisms that Cocoa provides to do that and ensure that isFoo’s clients are 
notified when the underlying value changes.

Charles

___

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: Translating KVO-ed property to Swift

2017-04-19 Thread Charles Srstka
> On Apr 19, 2017, at 4:50 PM, Quincey Morris 
> <quinceymor...@rivergatesoftware.com> wrote:
> 
> On Apr 19, 2017, at 10:56 , Charles Srstka <cocoa...@charlessoft.com> wrote:
>> 
>> 2. Stored properties need to call willChangeValue(forKey:) and 
>> didChangeValue(forKey:).
>>  a. In most cases, just add “dynamic” to the property declaration, and 
>> Cocoa will automagically insert the needed calls.
> 
> The problem with saying it this way is that it can be taken to imply that the 
> calls will be inserted statically *into the setter’s implementation*, which 
> is not true. It is true that Cocoa will automagically *execute* the needed 
> calls.
> 
> It also can be taken to imply that Cocoa does this automagically because the 
> property is dynamic, which is also not really true. Cocoa does this because 
> it’s a setter for an Obj-C property which returns true from its corresponding 
> automaticallyNotifiesObserversOfFoo class method. That is, “dynamic” doesn’t 
> turn the automagic behavior off or on, it’s simply a requirement to ensure 
> that the property is fully in the Obj-C domain.

Cocoa automagically does its secret subclass thing to wrap the setter and call 
the didChange/willChange calls for any property you didn’t tell it not to do. 
It needs the property to be dynamic for this to work. Thus, if you add 
“dynamic” to the property declaration, Cocoa will do the rest. That’s really 
all that’s relevant from a usage standpoint.

>> 3. Computed properties do not need to be dynamic, […].
> 
> This is also not exactly true. Computed properties that have only a getter do 
> not need to be dynamic, because they don’t generate any KVO notifications via 
> a setter, and so “dynamic” is irrelevant.
> 
> However, a computed property that has a setter will *not* produce the 
> expected notifications unless it is marked “dynamic”, even if marked “@objc”. 
> (I tested this to be sure.) There’s nothing special about computed vs. stored 
> properties in this regard.
> 
> I think you were “really” talking about derived properties, which are 
> typically computed properties with only a getter, no setter.

Nope, you can have a setter. You just have to make sure you’ve properly set up 
keyPathsForValuesAffecting. Here is some test code you can run yourself 
and verify this:

> import Foundation
> 
> class Foo: NSObject {
>   @objc dynamic var bar: String = ""
>   
>   @objc private static let keyPathsForValuesAffectingBaz: Set = 
> [#keyPath(bar)]
>   @objc var baz: String {
>   get { return self.bar }
>   set { self.bar = newValue }
>   }
>   
>   private var kvoContext = 0
>   
>   override init() {
>   super.init()
>   self.addObserver(self, forKeyPath: #keyPath(baz), options: [], 
> context: )
>   }
>   
>   override func observeValue(forKeyPath keyPath: String?, of object: 
> Any?, change: [NSKeyValueChangeKey : Any]?, context: 
> UnsafeMutableRawPointer?) {
>   if context ==  {
>   print("baz changed to \(self.baz)")
>   } else {
>   super.observeValue(forKeyPath: keyPath, of: object, 
> change: change, context: context)
>   }
>   }
> }
> 
> let foo = Foo()
> 
> foo.bar = "Bar"
> foo.baz = “Baz"

When run, this outputs:

baz changed to Bar
baz changed to Baz

Exactly as you would expect.

> In addition, “dynamic” is documented as needed, in the place I linked to 
> before:
> 
>   
> https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/AdoptingCocoaDesignPatterns.html#//apple_ref/doc/uid/TP40014216-CH7-ID6
> 
> under the heading Key-Value Observing where it says: "Add the dynamic 
> modifier to any property you want to observe.” This may be overly 
> conservative, but it is at least official.
> 
> For all those reasons, I think it’s pointless to try to figure out the 
> contexts where “dynamic” is unnecessary. It seems to me that the best advice 
> is that from the documentation: unconditionally add “dynamic” to any property 
> you want to observe. (Well, in the future, add “@objc dynamic”.)

It’s an oversimplification. If you understand the reasons why the ‘dynamic’ 
keyword is necessary, you will also be able to identify where it serves solely 
as unnecessary overhead.

Charles

___

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: Translating KVO-ed property to Swift

2017-04-19 Thread Quincey Morris
On Apr 19, 2017, at 10:56 , Charles Srstka <cocoa...@charlessoft.com> wrote:
> 
> 2. Stored properties need to call willChangeValue(forKey:) and 
> didChangeValue(forKey:).
>   a. In most cases, just add “dynamic” to the property declaration, and 
> Cocoa will automagically insert the needed calls.

The problem with saying it this way is that it can be taken to imply that the 
calls will be inserted statically *into the setter’s implementation*, which is 
not true. It is true that Cocoa will automagically *execute* the needed calls.

It also can be taken to imply that Cocoa does this automagically because the 
property is dynamic, which is also not really true. Cocoa does this because 
it’s a setter for an Obj-C property which returns true from its corresponding 
automaticallyNotifiesObserversOfFoo class method. That is, “dynamic” doesn’t 
turn the automagic behavior off or on, it’s simply a requirement to ensure that 
the property is fully in the Obj-C domain.

> 3. Computed properties do not need to be dynamic, […].

This is also not exactly true. Computed properties that have only a getter do 
not need to be dynamic, because they don’t generate any KVO notifications via a 
setter, and so “dynamic” is irrelevant.

However, a computed property that has a setter will *not* produce the expected 
notifications unless it is marked “dynamic”, even if marked “@objc”. (I tested 
this to be sure.) There’s nothing special about computed vs. stored properties 
in this regard.

I think you were “really” talking about derived properties, which are typically 
computed properties with only a getter, no setter.

In addition, “dynamic” is documented as needed, in the place I linked to before:


https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/AdoptingCocoaDesignPatterns.html#//apple_ref/doc/uid/TP40014216-CH7-ID6
 
<https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/AdoptingCocoaDesignPatterns.html#//apple_ref/doc/uid/TP40014216-CH7-ID6>

under the heading Key-Value Observing where it says: "Add the dynamic modifier 
to any property you want to observe.” This may be overly conservative, but it 
is at least official.

For all those reasons, I think it’s pointless to try to figure out the contexts 
where “dynamic” is unnecessary. It seems to me that the best advice is that 
from the documentation: unconditionally add “dynamic” to any property you want 
to observe. (Well, in the future, add “@objc dynamic”.)


___

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: Translating KVO-ed property to Swift

2017-04-19 Thread Charles Srstka
> On Apr 17, 2017, at 7:40 AM, Jean-Daniel <mail...@xenonium.com> wrote:
> 
>> Le 17 avr. 2017 à 10:52, Quincey Morris <quinceymor...@rivergatesoftware.com 
>> <mailto:quinceymor...@rivergatesoftware.com>> a écrit :
>> 
>> On Apr 17, 2017, at 01:43 , Jean-Daniel <mail...@xenonium.com 
>> <mailto:mail...@xenonium.com> <mailto:mail...@xenonium.com 
>> <mailto:mail...@xenonium.com>>> wrote:
>>> 
>>> var version: String? {
>> 
>> A slight correction: this declaration actually must be:
>> 
>>> dynamic var version: String? {
>> 
>> 
>> otherwise KVO isn’t guaranteed to work in Swift.
> 
> This is a good practice, but I don’t think this is required for computed 
> property, especially if you take care of willChange/didChange manually, as 
> the OP does.

Here’s the set of rules I recommend for writing KVO-compliant properties in 
Swift:

1. Always put @objc in front of every declaration involved, whether it’s the 
property itself or the static properties that are there to support it.

2. Stored properties need to call willChangeValue(forKey:) and 
didChangeValue(forKey:).
a. In most cases, just add “dynamic” to the property declaration, and 
Cocoa will automagically insert the needed calls.
b. If you call willChangeValue and didChangeValue manually, add the 
following static property, changing Foo to the property’s name. Since this is 
easy to misspell accidentally, it’s best to make an Xcode code snippet for it.

@objc private static let automaticallyNotifiesObserversOfFoo = false

3. Computed properties do not need to be dynamic, but should register their 
dependencies. The properties that form these dependencies also need to be 
KVO-compliant. To register dependencies, add the following static property. 
This is also helpful to set as an Xcode snippet to avoid typos.

@objc private static let keyPathsForValuesAffectingFoo: Set = 
[#keyPath(bar)]

The snippet above tells Cocoa that the KVO-compliant property “foo” depends on 
the KVO-compliant property “bar”, meaning that if “bar” changes, “foo”’s 
observers will be notified as well.

Charles

___

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: Translating KVO-ed property to Swift

2017-04-17 Thread Rick Mann
Thanks, Charles, that's helpful. In the end I left the class as Obj-C, because 
I still had to derive from it in Obj-C and you annoyingly can't do that.

> On Apr 17, 2017, at 08:06 , Charles Srstka <cocoa...@charlessoft.com> wrote:
> 
>> On Apr 17, 2017, at 3:24 AM, Rick Mann <rm...@latencyzero.com> wrote:
>> 
>> I have a number of properties in Objective-C written like this, 
>> short-circuiting notifications when the value doesn't change:
>> 
>> -
>> @synthesize version = mVersion
>> 
>> - (void)
>> setVersion: (NSString *) inVersion
>> {
>>if (inVersion == nil && mVersion == nil)
>>{
>>return;
>>}
>>if ([inVersion isEqualToString: mVersion])
>>{
>>return;
>>}
>> 
>>[self willChangeValueForKey: @"version"];
>>mVersion = inVersion;
>>[self didChangeValueForKey: @"version"];
>> }
>> -
>> 
>> Now I want to translate this method into Swift. Thing is, AFAIK you can't 
>> name the ivar created for a property. Is there a way to translate this to 
>> swift?
> 
> I’ve been converting a lot of KVO properties to Swift lately. Here’s how I’d 
> do this:
> 
> // Only needed if the property will be accessed by Objective-C code, since 
> Swift code won’t see the swizzled accessors anyway for a non-dynamic property.
> // @objc annotation is needed on every method we write here, since otherwise 
> it’ll quit working when @objc inference is removed in Swift 4 (SE-0160)
> @objc private static let automaticallyNotifiesObserversOfVersion: Bool = false
> 
> // Our actual version property. If you want, you can create a private 
> property named “mVersion” and it will function like an instance variable.
> // But I’d probably just use willSet and didSet.
> // Note that this doesn’t need to be dynamic, since we are not relying on 
> Cocoa’s built-in automatic swizzling,
> // which is only needed if we are not calling willChangeValue(forKey:) and 
> didChangeValue(forKey:) ourselves.
> @objc var version: String {
> willSet {
> // Send the willChange notification, if the value is different from 
> its old value.
> if newValue != self.version {
> self.willChangeValue(forKey: #keyPath(version))
> }
> }
> didSet {
> // Send the didChange notification, if the value is different from 
> its old value.
> if oldValue != self.version {
> self.didChangeValue(forKey: #keyPath(version))
> }
> }
> }
> 
> Charles
> 


-- 
Rick Mann
rm...@latencyzero.com


___

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: Translating KVO-ed property to Swift

2017-04-17 Thread Quincey Morris
On Apr 17, 2017, at 12:03 , Charles Srstka  wrote:
> 
> You cannot guarantee that the property will be called via objc_msgSend, which 
> is important if you’re relying on the swizzled accessor to send the property 
> notifications. If you’re sending them yourself, it doesn’t matter one way or 
> another how the property was called, as long as you add @objc so that clients 
> that do expect to be able to use objc_msgSend (most importantly, NSObject’s 
> observation support) can do it.

If you’re sending them yourself, then what matters is that you don’t 
*accidentally* let the property generate automatic notifications as well. There 
is only one way (AFAIK) to *guarantee* that automatic notifications aren’t 
generated as well, and that’s by returning false from 
‘automaticallyNotifiesObserversOfVersion’. There’s no other way in Swift 
(AFAIK) to ensure that, since there’s no “nondynamic” keyword. There’s also no 
other way in Obj-C (AFAIK) to ensure that.

This issue wasn’t supposed to be about Swift, though Swift makes it a bit 
murkier. Rick’s original code was wrong unless he had an Obj-C 
automaticallyNotifiesObserversOfVersion method elsewhere. For all I know, since 
he didn’t weigh back in with more information, he had that method all along.

> You also forgot the automaticallyNotifiesObserversOfVersion property in the 
> first bit of my example.

Yes, sorry, I just didn’t see it tucked up against the comment. Your code was 
correct in every detail.

___

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: Translating KVO-ed property to Swift

2017-04-17 Thread Charles Srstka
> On Apr 17, 2017, at 1:09 PM, Quincey Morris 
> <quinceymor...@rivergatesoftware.com> wrote:
> 
> On Apr 17, 2017, at 05:40 , Jean-Daniel <mail...@xenonium.com> wrote:
> 
>> This is a good practice, but I don’t think this is required for computed 
>> property, especially if you take care of willChange/didChange manually, as 
>> the OP does.
> 
> Here is what the Swift interoperability documentation says 
> (https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/AdoptingCocoaDesignPatterns.html):

And the reason for this is because Cocoa swizzles the accessor and adds the 
willChangeValue() and didChangeValue() calls. If you’re calling these yourself 
(or if you’re a computed property that registers its dependencies via 
keyPathsForValuesAffecting methods), you don’t need dynamic.

>> "You can use key-value observing with a Swift class, as long as the class 
>> inherits from the NSObject class. You can use these three steps to implement 
>> key-value observing in Swift.
>> 
>> "1. Add the dynamic modifier to any property you want to observe. […]”
> 
> Here is what the Swift language documentation says 
> (https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html):
> 
>> “dynamic”
>> 
>> "Apply this modifier to any member of a class that can be represented by 
>> Objective-C. When you mark a member declaration with the dynamic modifier, 
>> access to that member is always dynamically dispatched using the Objective-C 
>> runtime. Access to that member is never inlined or devirtualized by the 
>> compiler.”
> 
> That is, unless you specify “dynamic” there’s no *guarantee* that invocations 
> to the property accessors will use obj_msgSend, and since there’s no way in 
> Swift to guarantee that obj_msgSend *won’t* be used for the property, the 
> outcome for automatic KVO is unpredictable. 

You cannot guarantee that the property will be called via objc_msgSend, which 
is important if you’re relying on the swizzled accessor to send the property 
notifications. If you’re sending them yourself, it doesn’t matter one way or 
another how the property was called, as long as you add @objc so that clients 
that do expect to be able to use objc_msgSend (most importantly, NSObject’s 
observation support) can do it.

> On Apr 17, 2017, at 08:07 , Charles Srstka <cocoa...@charlessoft.com> wrote:
>> 
>> // Note that this doesn’t need to be dynamic, since we are not relying on 
>> Cocoa’s built-in automatic swizzling,
>> // which is only needed if we are not calling willChangeValue(forKey:) and 
>> didChangeValue(forKey:) ourselves.
>> @objc var version: String {
>>willSet {
>>// Send the willChange notification, if the value is different from 
>> its old value.
>>if newValue != self.version {
>>self.willChangeValue(forKey: #keyPath(version))
>>}
>>}
>>didSet {
>>// Send the didChange notification, if the value is different from 
>> its old value.
>>if oldValue != self.version {
>>self.didChangeValue(forKey: #keyPath(version))
>>}
>>}
>> }
> 
> I tested what happens (in Swift 3.1, Xcode 8.3.1) using this code:
> 
>> private var versionContext = 0
>> 
>> class ViewController: NSViewController {
>>  @objc /*dynamic*/ var version: String = “” {
>>  willSet {
>>  if newValue != self.version {
>>  self.willChangeValue (forKey: 
>> #keyPath(version)) }
>>  }
>>  didSet {
>>  if oldValue != self.version {
>>  self.didChangeValue (forKey: #keyPath(version)) 
>> }
>>  }
>>  }
>>  override func viewDidLoad () {
>>  super.viewDidLoad ()
>>  addObserver (self, forKeyPath: #keyPath(version), options: [], 
>> context: )
>>  }
>>  override func observeValue (forKeyPath keyPath: String?,  of object: 
>> Any?,  change: [NSKeyValueChangeKey : Any]?,  context: 
>> UnsafeMutableRawPointer?) {
>>  print ("observedValue for \(version)")
>>  }
>>  @IBAction func buttonClicked (_ sender: Any?) { // There’s a button in 
>> the UI hooked up to this
>>  version = version == "" ? "1" : "\(version)"
>>  }
>> }
> 
> This version of the code (with “dynamic” commented out) displays the observer 
> message once, as des

Re: Translating KVO-ed property to Swift

2017-04-17 Thread Quincey Morris
On Apr 17, 2017, at 05:40 , Jean-Daniel <mail...@xenonium.com> wrote:

> This is a good practice, but I don’t think this is required for computed 
> property, especially if you take care of willChange/didChange manually, as 
> the OP does.

Here is what the Swift interoperability documentation says 
(https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/AdoptingCocoaDesignPatterns.html):

> "You can use key-value observing with a Swift class, as long as the class 
> inherits from the NSObject class. You can use these three steps to implement 
> key-value observing in Swift.
> 
> "1. Add the dynamic modifier to any property you want to observe. […]”

Here is what the Swift language documentation says 
(https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html):

> “dynamic”
> 
> "Apply this modifier to any member of a class that can be represented by 
> Objective-C. When you mark a member declaration with the dynamic modifier, 
> access to that member is always dynamically dispatched using the Objective-C 
> runtime. Access to that member is never inlined or devirtualized by the 
> compiler.”


That is, unless you specify “dynamic” there’s no *guarantee* that invocations 
to the property accessors will use obj_msgSend, and since there’s no way in 
Swift to guarantee that obj_msgSend *won’t* be used for the property, the 
outcome for automatic KVO is unpredictable. 

On Apr 17, 2017, at 08:07 , Charles Srstka <cocoa...@charlessoft.com> wrote:
> 
> // Note that this doesn’t need to be dynamic, since we are not relying on 
> Cocoa’s built-in automatic swizzling,
> // which is only needed if we are not calling willChangeValue(forKey:) and 
> didChangeValue(forKey:) ourselves.
> @objc var version: String {
>willSet {
>// Send the willChange notification, if the value is different from 
> its old value.
>if newValue != self.version {
>self.willChangeValue(forKey: #keyPath(version))
>}
>}
>didSet {
>// Send the didChange notification, if the value is different from its 
> old value.
>if oldValue != self.version {
>self.didChangeValue(forKey: #keyPath(version))
>}
>}
> }

I tested what happens (in Swift 3.1, Xcode 8.3.1) using this code:

> private var versionContext = 0
> 
> class ViewController: NSViewController {
>   @objc /*dynamic*/ var version: String = “” {
>   willSet {
>   if newValue != self.version {
>   self.willChangeValue (forKey: 
> #keyPath(version)) }
>   }
>   didSet {
>   if oldValue != self.version {
>   self.didChangeValue (forKey: #keyPath(version)) 
> }
>   }
>   }
>   override func viewDidLoad () {
>   super.viewDidLoad ()
>   addObserver (self, forKeyPath: #keyPath(version), options: [], 
> context: )
>   }
>   override func observeValue (forKeyPath keyPath: String?,  of object: 
> Any?,  change: [NSKeyValueChangeKey : Any]?,  context: 
> UnsafeMutableRawPointer?) {
>   print ("observedValue for \(version)")
>   }
>   @IBAction func buttonClicked (_ sender: Any?) { // There’s a button in 
> the UI hooked up to this
>   version = version == "" ? "1" : "\(version)"
>   }
> }

This version of the code (with “dynamic” commented out) displays the observer 
message once, as desired, and then not again, as desired. Uncommenting 
“dynamic” causes the message to be displayed twice the first time, and then 
once more every subsequent button click.

So, Charles’s approach *appears* to work, because the “version” property isn’t 
participating in automatic swizzling. However, it’s subtly wrong because 
there’s no way to prevent other source code from leading the compiler to 
*deduce* that the method is dynamic. Once that happens, there’s an extra 
unwanted notification every time the property is set.

And again, in the converse scenario (automatic KVO, where you want 
notifications unconditionally) the “dynamic” keyword isn’t optional.

The correct solution, I claim, is to replace the declaration of “version” with 
this:

>   static func automaticallyNotifiesObserversOfVersion () -> Bool { return 
> false }
>   @objc dynamic var version: String = “” { … }

and then use either Charles’ or Jean-Daniel’s logic to generate the 
notifications manually as desired.

(BTW, the “@objc” is currently redundant, but will soon become required, via 
SE-0160 
<https://github.com/apple/swift-evolution/blob/master/proposals/0160

Re: Translating KVO-ed property to Swift

2017-04-17 Thread Charles Srstka
> On Apr 17, 2017, at 3:24 AM, Rick Mann <rm...@latencyzero.com> wrote:
> 
> I have a number of properties in Objective-C written like this, 
> short-circuiting notifications when the value doesn't change:
> 
> -
> @synthesize version = mVersion
> 
> - (void)
> setVersion: (NSString *) inVersion
> {
>if (inVersion == nil && mVersion == nil)
>{
>return;
>}
>if ([inVersion isEqualToString: mVersion])
>{
>return;
>}
> 
>[self willChangeValueForKey: @"version"];
>mVersion = inVersion;
>[self didChangeValueForKey: @"version"];
> }
> -
> 
> Now I want to translate this method into Swift. Thing is, AFAIK you can't 
> name the ivar created for a property. Is there a way to translate this to 
> swift?

I’ve been converting a lot of KVO properties to Swift lately. Here’s how I’d do 
this:

// Only needed if the property will be accessed by Objective-C code, since 
Swift code won’t see the swizzled accessors anyway for a non-dynamic property.
// @objc annotation is needed on every method we write here, since otherwise 
it’ll quit working when @objc inference is removed in Swift 4 (SE-0160)
@objc private static let automaticallyNotifiesObserversOfVersion: Bool = false

// Our actual version property. If you want, you can create a private property 
named “mVersion” and it will function like an instance variable.
// But I’d probably just use willSet and didSet.
// Note that this doesn’t need to be dynamic, since we are not relying on 
Cocoa’s built-in automatic swizzling,
// which is only needed if we are not calling willChangeValue(forKey:) and 
didChangeValue(forKey:) ourselves.
@objc var version: String {
willSet {
// Send the willChange notification, if the value is different from its 
old value.
if newValue != self.version {
self.willChangeValue(forKey: #keyPath(version))
}
}
didSet {
// Send the didChange notification, if the value is different from its 
old value.
if oldValue != self.version {
self.didChangeValue(forKey: #keyPath(version))
}
}
}

Charles

___

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: Translating KVO-ed property to Swift

2017-04-17 Thread Jean-Daniel

> Le 17 avr. 2017 à 10:52, Quincey Morris <quinceymor...@rivergatesoftware.com> 
> a écrit :
> 
> On Apr 17, 2017, at 01:43 , Jean-Daniel <mail...@xenonium.com 
> <mailto:mail...@xenonium.com>> wrote:
>> 
>> var version: String? {
> 
> A slight correction: this declaration actually must be:
> 
>> dynamic var version: String? {
> 
> 
> otherwise KVO isn’t guaranteed to work in Swift.

This is a good practice, but I don’t think this is required for computed 
property, especially if you take care of willChange/didChange manually, as the 
OP does.


___

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: Translating KVO-ed property to Swift

2017-04-17 Thread Quincey Morris
On Apr 17, 2017, at 01:43 , Jean-Daniel <mail...@xenonium.com> wrote:
> 
> var version: String? {

A slight correction: this declaration actually must be:

> dynamic var version: String? {


otherwise KVO isn’t guaranteed to work in Swift.

___

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: Translating KVO-ed property to Swift

2017-04-17 Thread Quincey Morris
On Apr 17, 2017, at 01:24 , Rick Mann  wrote:
> 
> I have a number of properties in Objective-C written like this, 
> short-circuiting notifications when the value doesn't change:

Not in this code you don’t, unless you have a 
“automaticallyNotifiesObserversOfVersion” method returning false elsewhere in 
the class. The notification doesn’t happen in the synthesized implementation of 
the setter, but via a swizzled replacement setter that is normally installed 
only when something starts observing the property. Anyway …

> Now I want to translate this method into Swift. Thing is, AFAIK you can't 
> name the ivar created for a property. Is there a way to translate this to 
> swift?

You do it in the “obvious” way — you declare a second, private property without 
a custom getter or setter, and you use this private property where you would 
have used the instance variable in Obj-C. The effect is the same, because the 
private property is optimized into just an instance variable, and the public 
property has no instance storage of its own (but you will have to provide a 
custom getter, too).

___

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: Translating KVO-ed property to Swift

2017-04-17 Thread Jean-Daniel
One way to solve that is to declare an explicit private stored property for the 
ivar, and a public computed property for the logic.

private var _version: String? = nil

var version: String? {
get { return _version }
set { your set version code }
}


> Le 17 avr. 2017 à 10:24, Rick Mann  a écrit :
> 
> I have a number of properties in Objective-C written like this, 
> short-circuiting notifications when the value doesn't change:
> 
> -
> @synthesize version = mVersion
> 
> - (void)
> setVersion: (NSString *) inVersion
> {
>if (inVersion == nil && mVersion == nil)
>{
>return;
>}
>if ([inVersion isEqualToString: mVersion])
>{
>return;
>}
> 
>[self willChangeValueForKey: @"version"];
>mVersion = inVersion;
>[self didChangeValueForKey: @"version"];
> }
> -
> 
> Now I want to translate this method into Swift. Thing is, AFAIK you can't 
> name the ivar created for a property. Is there a way to translate this to 
> swift?
> 
> TIA,
> 
> -- 
> Rick Mann
> rm...@latencyzero.com
> 
> 
> ___
> 
> 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/mailing%40xenonium.com
> 
> This email sent to mail...@xenonium.com

___

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

Translating KVO-ed property to Swift

2017-04-17 Thread Rick Mann
I have a number of properties in Objective-C written like this, 
short-circuiting notifications when the value doesn't change:

-
@synthesize version = mVersion

- (void)
setVersion: (NSString *) inVersion
{
if (inVersion == nil && mVersion == nil)
{
return;
}
if ([inVersion isEqualToString: mVersion])
{
return;
}

[self willChangeValueForKey: @"version"];
mVersion = inVersion;
[self didChangeValueForKey: @"version"];
}
-

Now I want to translate this method into Swift. Thing is, AFAIK you can't name 
the ivar created for a property. Is there a way to translate this to swift?

TIA,

-- 
Rick Mann
rm...@latencyzero.com


___

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: Can't access by data via KVC during KVO

2017-03-27 Thread Quincey Morris
On Mar 27, 2017, at 14:48 , Daryle Walker  wrote:
> 
> The message observation points to the object controller’s “selection”, then a 
> specific property of my model (of type “String?”).

>> Could not cast value of type '_NSStateMarker' (0x7fffa3003cf8) to 'NSString' 
>> (0x7fffa397df38).
>> 2017-03-27 16:36:33.978709 XNW[39160:4830169] Could not cast value of type 
>> '_NSStateMarker' (0x7fffa3003cf8) to 'NSString' (0x7fffa397df38).
> 
> What is this “NSStateMarker” class? And why does it prevent me from accessing 
> the data?

In short, you shouldn’t be using the “selection” property as if it means 
something for an object controller. Yes, you *can* select an object in the 
object controller’s content as *the* selection, but it doesn’t help you with 
anything — it doesn’t represent anything in the UI.**

By definition, the “selection” is a proxy for an object (NSObjectController) or 
an array of objects (NSArrayController, which is a *subclass* of 
NSObjectController), but it can also represent a marker value, indicating no 
selection or multiple selection or (IIRC) some other possibilities. I assume 
your crash occurred because at the time you referenced “selection” it was set 
to one of these markers, and hence not castable to a String.

Programming (in the sense of writing actual code) against NS…Controller objects 
is a horrible and dangerous experience, because they’re black boxes and you’ll 
never know what they’re really doing internally. I strongly, strongly recommend 
that you program against the data model directly. There’s no value (that I know 
of) in referencing a NSObjectController as you have. NSArrayController is a bit 
less clear, because if you’re using it to fetch, sort and filter Core Data 
records, then you sort of think you need to use its arrangedObjects property. 
Still, you don’t have to go through a NSArrayController — there’s nothing wrong 
with fetching, sorting and filtering Core Data records yourself.


** I’ve never really understood for sure, but I think the point of having a 
selection is that (by default in IB) NSObjectController models a 
NSMutableDictionary, and it can distinguish between multiple keys “within” the 
“dictionary” that are in most cases just different properties of the content 
object. By binding to “selection” and switching the selection, you can switch 
which key supplies a value to a single UI field (like a primitive master-detail 
arrangement).

In fact, what normally happens is that the keys just represent independent 
objects accessible via the content object, and each of them is bound directly 
to its own UI element. In this case, the selection basically has no meaning.
___

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

Can't access by data via KVC during KVO

2017-03-27 Thread Daryle Walker
This is from my window controller class, which has a (optional) reference to my 
document subclass’s model data. Through Interface Builder, that data is 
connected to a NSObjectController, and a property of that data is connected to 
a NSArrayController. The window controller has outlets to both data 
controllers. The model data is Core Data-based, BTW.

I have to watch the data as part of my scheme to create a character map to use 
for NSTextFinder. Instead of KVO-ing the model data, I do the two data 
controllers instead since those are the “truth” I need to track (in case they 
cache any editing changes).

> headerController.addObserver(self, forKeyPath: 
> MessageWindowController.headerKeyPath, options: .initial, context: 
> )
> messageController.addObserver(self, forKeyPath: 
> MessageWindowController.bodyKeyPath, options: .initial, context: 
> )

The header observation points to the array controller’s “arrangedObjects”. The 
message observation points to the object controller’s “selection”, then a 
specific property of my model (of type “String?”). I try to test an incomplete 
version of the KVO function:

> override func observeValue(forKeyPath keyPath: String?, of object: Any?, 
> change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
> guard let keyPath2 = keyPath, let object2 = object, let change2 = 
> change, let context2 = context else {
> return super.observeValue(forKeyPath: keyPath, of: object, 
> change: change, context: context)
> }
> 
> let changeKind = NSKeyValueChange(rawValue: change2[.kindKey] as! 
> UInt)!
> switch context2 {
> case :
> precondition(keyPath2 == MessageWindowController.headerKeyPath)
> precondition(object2 as AnyObject === headerController)
> break
> case :
> precondition(keyPath2 == MessageWindowController.bodyKeyPath)
> precondition(object2 as AnyObject === messageController)
> assert(changeKind == .setting)
> 
> let newString = (messageController.selection as! 
> NSObject).value(forKey: #keyPath(RawMessage.body)) as! String? 
> //messageController.value(forKeyPath: keyPath2) as! String?
> let bodyTextRangeIndex = textRanges.index(before: 
> textRanges.endIndex)
> let oldBodyTextRange = textRanges[bodyTextRangeIndex]
> let newLength = (newString as NSString?)?.length ?? 0
> if oldBodyTextRange.length != newLength {
> textRanges[bodyTextRangeIndex] = 
> NSMakeRange(oldBodyTextRange.location, newLength)
> }
> break
> default:
> super.observeValue(forKeyPath: keyPath2, of: object2, change: 
> change2, context: context2)
> }
> }

And there’s a crash at the “newString” definition. (The current and 
commented-out versions get the same error. The current version was copied from 
my menu-item validation function, where it actually works.):

> Could not cast value of type '_NSStateMarker' (0x7fffa3003cf8) to 'NSString' 
> (0x7fffa397df38).
> 2017-03-27 16:36:33.978709 XNW[39160:4830169] Could not cast value of type 
> '_NSStateMarker' (0x7fffa3003cf8) to 'NSString' (0x7fffa397df38).

What is this “NSStateMarker” class? And why does it prevent me from accessing 
the data?

Do NSObjectController and/or NSArrayController do any caching of its editing 
data? If not, and we can’t directly solve this problem, I could read the data 
directly from the document’s model objects.

Pre-Send Update:

I took out the “.initial” from the observing setup call, and it works! Why is 
that? Now I have to hope that my concept of the initial text-range array is 
accurate, since I can’t confirm it with an initial pass (for now).

Note that when the window controller goes through “windowDidLoad”, the 
reference to the model data is NIL. (The object and array controllers are still 
bound to it by then, though.) It doesn’t get set to an actual data tree until 
the document’s “makeWindowControllers” call.

Pre-Send Update 2:

I completed a first try for the other property:

> let changeKind = NSKeyValueChange(rawValue: change2[.kindKey] as! 
> UInt)!
> let bodyTextRangeIndex = textRanges.index(before: textRanges.endIndex)
> switch context2 {
> case :
> precondition(keyPath2 == MessageWindowController.headerKeyPath)
> precondition(object2 as AnyObject === headerController)
> 
> let newArray = headerController.mutableArrayValue(forKeyPath: 
> keyPath2) as NSArray
> switch changeKind {
> case .insertion, .removal, .replacement:
> fallthrough
> case .setting:
> var newFieldRanges = R

Re: MLMediaLibrary sometimes does not call my KVO

2016-10-07 Thread Gabriel Zachmann

___

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: MLMediaLibrary sometimes does not call my KVO

2016-10-04 Thread Gabriel Zachmann
> It’s very hard for a sandboxed app to get access to the internals of Photos 
> without using MLMediaLibrary, though not too difficult for non-sandboxed. 
> MLMediaLibrary was added because of this need.

I was wondering whether this API (Photos Framework aka PhotoKit) would be 
better suited :
  https://developer.apple.com/reference/photos?language=objc

According to the doc, it should be available on macOS 10.11+

Best regards, 
Gabriel.


___

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: MLMediaLibrary sometimes does not call my KVO

2016-09-22 Thread Graham Cox

> On 22 Sep 2016, at 10:45 PM, Gabriel Zachmann <z...@tu-clausthal.de> wrote:
> 
>> I’ve run into some unreliability in MLMediaLibrary. It appears to be a bug 
>> because it sometimes can be seen in places that use MLMediaLibrary within 
>> general standard components, such as NSOpenPanel (this adds a media browsing 
>> section if it is set up to allow image types, for example). 
> 
> Thanks a lot for your insights.
> 
> I am wondering: how does Microsoft Word , for instance, do it?
> I've never seen that application behave funny when it shows the image browser 
> (it faithfully shows all 10,000 images from my Photos library).
> 
> Does it use a different API?

It’s very hard for a sandboxed app to get access to the internals of Photos 
without using MLMediaLibrary, though not too difficult for non-sandboxed. 
MLMediaLibrary was added because of this need.

There is a standard component - NSMediaLibraryBrowserController 
(https://developer.apple.com/reference/appkit/nsmedialibrarybrowsercontroller?language=objc)
 that gives you a standardised panel for browsing. Unfortunately it’s a 
standalone panel rather than a view that you can embed within a larger UI, but 
it’s sufficient for many needs, and is easy to use. You could look at that and 
see if its behaviour is more reliable than your own code. I have tried it and 
it isn’t for me - I get the same problems with it that I see in NSOpenPanel, or 
when using KVO on MLMediaLibrary elements, which is why the problem seems to be 
in the lower-level layers of MLMediaLibrary.

—Graham



___

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: MLMediaLibrary sometimes does not call my KVO

2016-09-22 Thread Gabriel Zachmann
> I’ve run into some unreliability in MLMediaLibrary. It appears to be a bug 
> because it sometimes can be seen in places that use MLMediaLibrary within 
> general standard components, such as NSOpenPanel (this adds a media browsing 
> section if it is set up to allow image types, for example). 

Thanks a lot for your insights.

I am wondering: how does Microsoft Word , for instance, do it?
I've never seen that application behave funny when it shows the image browser 
(it faithfully shows all 10,000 images from my Photos library).

Does it use a different API?

Best regards, 
Gabriel.





___

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: MLMediaLibrary sometimes does not call my KVO

2016-09-21 Thread Graham Cox

> On 22 Sep 2016, at 8:59 AM, Gabriel Zachmann <z...@tu-clausthal.de> wrote:
> 
> I am a bit at a loss about the MLMediaLibrary API.
> Maybe, I haven't quite understood it yet, maybe something else is wrong.
> 
> I am writing a screen saver that accesses Photos' albums and the images 
> referenced by them.
> (Code excerpts follow at the end of this email.)
> 
> I create an array of the top level albums at startup time of the screensaver 
> , using the KVO.
> At runtime, I occasionally extract the images referenced by one of those 
> albums.
> Most of the time it works fine, except sometimes, my KVO never gets invoked, 
> at which point my screensaver hangs,
> because I had to stop the animation during that phase.
> 
> I have not found a pattern as to when this happens.
> (it is not a deterministic album, nor a deterministic n-th time.)
> 
> Any suggestions, hints, insights, and pointers will be highly appreciated.


I’ve run into some unreliability in MLMediaLibrary. It appears to be a bug 
because it sometimes can be seen in places that use MLMediaLibrary within 
general standard components, such as NSOpenPanel (this adds a media browsing 
section if it is set up to allow image types, for example). Sometimes it only 
shows the top level of the library, and all of the subgroups are simply 
missing, and never show up no matter how long you wait. Opening the panel a 
second time will finally deliver the subgroups.

My guess is that as it’s an asynchronous API, on the first pass the system has 
to build a lot of internal cached state, and it may fail for any reason. On the 
second pass, it has already primed much of that cache and the failure doesn’t 
occur. While this happens quite often, it’s not every time, so I haven’t 
spotted an absolute pattern.

But I think your code needs to be designed in such a way that if the KVO it is 
expecting (for the contents of a given group, say) is never delivered, it 
doesn’t fail. I’m not sure that is really possible for a photos screensaver (in 
that case you have no photos to display), but there’s no reason it needs to 
hang.

Hopefully 10.12 will fix the issue, but I haven’t had a chance to look into 
that yet.

—Graham



___

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

MLMediaLibrary sometimes does not call my KVO

2016-09-21 Thread Gabriel Zachmann
I am a bit at a loss about the MLMediaLibrary API.
Maybe, I haven't quite understood it yet, maybe something else is wrong.

I am writing a screen saver that accesses Photos' albums and the images 
referenced by them.
(Code excerpts follow at the end of this email.)

I create an array of the top level albums at startup time of the screensaver , 
using the KVO.
At runtime, I occasionally extract the images referenced by one of those albums.
Most of the time it works fine, except sometimes, my KVO never gets invoked, at 
which point my screensaver hangs,
because I had to stop the animation during that phase.

I have not found a pattern as to when this happens.
(it is not a deterministic album, nor a deterministic n-th time.)

Any suggestions, hints, insights, and pointers will be highly appreciated.

Best regards, 
Gabriel.


The code snippets.  (variables ending with underscore are instance variables.)


This is what I do at startup time (in -initwithFrame:isPreview:)


   albums_ = [[NSMutableArray alloc] init];
   NSDictionary *options = @{
 MLMediaLoadSourceTypesKey: 
@(MLMediaSourceTypeImage),
 MLMediaLoadIncludeSourcesKey: 
@[MLMediaSourcePhotosIdentifier]
 };
   mediaLibrary_ = [[MLMediaLibrary alloc] initWithOptions: options];
   [mediaLibrary_ addObserver: self
   forKeyPath: @"mediaSources"
  options: 0
  context: (__bridge void *) @"mediaLibraryLoaded"];
   [mediaLibrary_.mediaSources objectForKey: MLMediaSourcePhotosIdentifier ];  
// starts asynchronous loading


During runtime, this gets executed occasionally:


   album_ = albums_[album_id];
   [album_ addObserver: self
forKeyPath: @"mediaObjects"
   options: 0
   context: @"mediaObjects"];
   [album_ mediaObjects];


I have checked using log message that addObserver: does actually get executed.


And this is my key value observer:


- (void) observeValueForKeyPath: (NSString *) keyPath   ofObject: (id) object
change: (NSDictionary *) change context: (void *) 
context
{
   MLMediaSource * mediaSource = [mediaLibrary_.mediaSources objectForKey: 
MLMediaSourcePhotosIdentifier];
   if ( context == (__bridge void *) @"mediaLibraryLoaded" )
   {
   [mediaSource addObserver: self
 forKeyPath: @"rootMediaGroup"
options: 0
context: (__bridge void *) @"rootMediaGroupLoaded"];
   [mediaSource rootMediaGroup];   
// start next phase: load groups
   }
   else if ( context == (__bridge void *) @"rootMediaGroupLoaded" )
   {
   MLMediaGroup *albums = [mediaSource mediaGroupForIdentifier: 
@"TopLevelAlbums"];
   for ( MLMediaGroup * album in albums.childGroups )
   {
   NSString * albumName = [album.attributes objectForKey: @"name"];
   [self logMessage: [NSString stringWithFormat: @"album name = %@", 
albumName] asError: NO];
   if ( albumName )
   [albums_ addObject: album ];
   }
   }
   else if ( context == (__bridge void *) @"mediaObjects" )
   {
   NSArray * mediaObjects = album_.mediaObjects;   
   for ( MLMediaObject * mediaObject in mediaObjects )
   {
   if ( mediaObject.mediaType != MLMediaTypeImage )
   // we still get movies as mediaObjects, which might be contained 
in a Photos album
   continue;

   NSURL * url  = mediaObject.URL;
   [photoPaths_ addObject: url.path];
   }
   }
}


Again, I checked with a log message that the KVO never gets invoked in the case 
when the screen saver hangs
(i.e., I am positive the hanging is not caused by an infinite loop or similar 
in the KVO.)




___

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: iOS - the joy of observers and NSInternalInconsistancyException for KVO

2016-05-19 Thread Roland King

> On 20 May 2016, at 07:04, Roland King  wrote:
> 
> 
> Reading the original post he already has the warning about an object being 
> deallocated whilst still having observers attached to it. 
> 
> This is simply a case of putting a breakpoint on dealloc and working out why 
> the object is being deallocated before you’ve gone through the observation 
> removal code you have. 

.. and if you want a condition you can put on a conditional breakpoint inside 
dealloc (or swift equivalent), checking self.observationInfo != nil may help to 
get the right dealloc. And that object, even though it’s actually opaque and 
internal and not-to-be-used, when printed will reveal some hints about who is 
still observing you .. at least in objC, I’ve never got the right commands to 
make LLDB use the objC print to show it. 

Just for clarity - I’m not suggesting using observationInfo to ‘prevent 
dealloc’, which you can’t do anyway and even if you could would be somewhere 
just the other side of insane, just to help filter out during debugging which 
dealloc to break on. 
___

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: iOS - the joy of observers and NSInternalInconsistancyException for KVO

2016-05-19 Thread Roland King

> On 20 May 2016, at 04:36, Jens Alfke <j...@mooseyard.com> wrote:
> 
> 
>> On May 19, 2016, at 1:24 PM, Alex Zavatone <z...@mac.com> wrote:
>> 
>> In this case, I'm trying to see what is causing this deallocation.  In my 
>> code, I explicitly remove the observer before I nil the object, so I don't 
>> know where this is happening.  
> 
> If you’re observing an object, you should probably establish a strong 
> reference to it, like by assigning it to an ivar or adding it to an array or 
> something. Otherwise you can’t guarantee that it will stay alive. But since 
> say “nil the object”, which I guess means “nil a variable pointing to the 
> object”, then you should already have a strong reference, so the object 
> shouldn’t get dealloced unless you’ve got a ref-counting error somewhere. (Do 
> you use ARC?)
> 
> There is a user default NSBindingDebugLogLevel on Mac OS that you can set to 
> 1, which will generate extra warnings about KVO and bindings. It might do 
> something useful in your case; I can’t remember exactly what it does, but it 
> may produce a warning when an object with observers gets dealloced.
> 
> —Jens

Reading the original post he already has the warning about an object being 
deallocated whilst still having observers attached to it. 

This is simply a case of putting a breakpoint on dealloc and working out why 
the object is being deallocated before you’ve gone through the observation 
removal code you have. 
___

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: iOS - the joy of observers and NSInternalInconsistancyException for KVO

2016-05-19 Thread Jens Alfke

> On May 19, 2016, at 1:24 PM, Alex Zavatone <z...@mac.com> wrote:
> 
> In this case, I'm trying to see what is causing this deallocation.  In my 
> code, I explicitly remove the observer before I nil the object, so I don't 
> know where this is happening.  

If you’re observing an object, you should probably establish a strong reference 
to it, like by assigning it to an ivar or adding it to an array or something. 
Otherwise you can’t guarantee that it will stay alive. But since say “nil the 
object”, which I guess means “nil a variable pointing to the object”, then you 
should already have a strong reference, so the object shouldn’t get dealloced 
unless you’ve got a ref-counting error somewhere. (Do you use ARC?)

There is a user default NSBindingDebugLogLevel on Mac OS that you can set to 1, 
which will generate extra warnings about KVO and bindings. It might do 
something useful in your case; I can’t remember exactly what it does, but it 
may produce a warning when an object with observers gets dealloced.

—Jens
___

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: iOS - the joy of observers and NSInternalInconsistancyException for KVO

2016-05-19 Thread Alex Zavatone

On May 19, 2016, at 2:10 PM, Jens Alfke wrote:

> 
>> On May 19, 2016, at 9:54 AM, Alex Zavatone <z...@mac.com> wrote:
>> 
>> OK, fair enough.  Looks like I'll have build a little weak referenced dealy 
>> that subclasses dealloc and stops if it detects any observers. 
> 
> Holy crap, don’t do that. First, you can’t stop a dealloc. Instead you’d have 
> to override retain and release, which is very tricky and will break ARC. 
> Second, needing to do this is a sure sign that You’re Doing It Wrong — it’s 
> like one of those images captioned FAIL where someone’s done some crime 
> against nature using duct tape.

I have no means to see why this is happening at this point.  If I have sinned 
against nature or if nature is sinning against me, I can't tell yet; duct tape 
be damned.

> What is the problem exactly? Who is observing what?

In this case, I'm trying to see what is causing this deallocation.  In my code, 
I explicitly remove the observer before I nil the object, so I don't know where 
this is happening.  

On iOS, part of my app downloads files over https using NSURLSession.  Not a 
problem.  In a manager class, I perform this operation "get the list of files 
from our web end point and then download everything one file at a time 
asynchronously".  I thought it would be fun to use KVO to observe when the 
downloaded file is saved into its final path and then iterate to the next item 
in the list. However, when I switch to one of our pre release web end points, 
we use self signed certs and I haven't had the time to implement the 
challenge/response code yet.  This causes the NSURLSession to clear itself 
somehow.  Now that a failure case has reared its ugly head, I'd like to know 
why the object is removing itself before I am removing the observer.

I want to catch the point where dealloc is being called and the object is still 
being observed, so I can see why this is happening on this failure case.

> —Jens

___

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: iOS - the joy of observers and NSInternalInconsistancyException for KVO

2016-05-19 Thread Alex Zavatone
Yeah, I have strong references too, but some part of my NSURLSession code ends 
up causing this error when we have a failure (SSL challenge) on a file download.

I'll have to implement the methods to handle the download failure cases, which 
I am currently not doing.

On May 19, 2016, at 12:57 PM, Jonathan Mitchell wrote:

> 
>> On 19 May 2016, at 17:55, Jonathan Mitchell  wrote:
>> 
>> That way the observed object can get deallocated before the observer.
> Should say 
> That way the observed object cannot get deallocated before the observer.
> 
> J
> 
> ___
> 
> 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/zav%40mac.com
> 
> This email sent to z...@mac.com


___

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: iOS - the joy of observers and NSInternalInconsistancyException for KVO

2016-05-19 Thread Jens Alfke

> On May 19, 2016, at 9:54 AM, Alex Zavatone  wrote:
> 
> OK, fair enough.  Looks like I'll have build a little weak referenced dealy 
> that subclasses dealloc and stops if it detects any observers. 

Holy crap, don’t do that. First, you can’t stop a dealloc. Instead you’d have 
to override retain and release, which is very tricky and will break ARC. 
Second, needing to do this is a sure sign that You’re Doing It Wrong — it’s 
like one of those images captioned FAIL where someone’s done some crime against 
nature using duct tape.

What is the problem exactly? Who is observing what?

—Jens
___

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: iOS - the joy of observers and NSInternalInconsistancyException for KVO

2016-05-19 Thread Jonathan Mitchell

> On 19 May 2016, at 17:55, Jonathan Mitchell  wrote:
> 
> That way the observed object can get deallocated before the observer.
Should say 
That way the observed object cannot get deallocated before the observer.

J

___

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: iOS - the joy of observers and NSInternalInconsistancyException for KVO

2016-05-19 Thread Jonathan Mitchell

> 
> Is there any safer KVO technique to prevent or detect the dreaded "An 
> instance of xx was deallocated while key value observers were still 
> registered with it"?
> 
I have a ton of observers in NSViewController subclasses.
Generally when I use an observer I make 100% sure I have a strong property 
reference (held by the NSViewController instance) to the observed object.
That way I know that the observed object will live as long as the 
NSViewController.
That way the observed object can get deallocated before the observer.
I then always make sure to remove my observers in NSViewController -dealloc.

If you want the observer to stop observing on command then use a delegate 
pattern or a notification to explicitly request that.

It is a futile task IMHO to dig into the KVO machinery and try and second guess 
it.

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: iOS - the joy of observers and NSInternalInconsistancyException for KVO

2016-05-19 Thread Alex Zavatone

On May 19, 2016, at 12:41 PM, Jens Alfke wrote:

> 
>> On May 19, 2016, at 7:51 AM, Alex Zavatone  wrote:
>> 
>> Is there a means to have an object know when it's being observed so that it 
>> will refuse to nuke itself in this condition?
> 
> Nope. Remember, objects don’t “nuke” themselves; they are dealloced when no 
> other objects have references to them. It’s the observer’s responsibility to 
> retain a reference to the target object (observee?) for as long as it’s 
> observing that object. Or at least to have some means of detecting that the 
> target object is going to go away, and removing itself as an observer then.
> 
> —Jens

OK, fair enough.  Looks like I'll have build a little weak referenced dealy 
that subclasses dealloc and stops if it detects any observers.  Then for any 
object that I plan on being KVOable, it will have to be be a subclass of 
NSObject+bubblewrappedKVO, if dealloc is called while observers are still on 
the object.

Thank you, sir.

Alex Zavatone
___

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: iOS - the joy of observers and NSInternalInconsistancyException for KVO

2016-05-19 Thread Jens Alfke

> On May 19, 2016, at 7:51 AM, Alex Zavatone  wrote:
> 
> Is there a means to have an object know when it's being observed so that it 
> will refuse to nuke itself in this condition?

Nope. Remember, objects don’t “nuke” themselves; they are dealloced when no 
other objects have references to them. It’s the observer’s responsibility to 
retain a reference to the target object (observee?) for as long as it’s 
observing that object. Or at least to have some means of detecting that the 
target object is going to go away, and removing itself as an observer then.

—Jens
___

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

iOS - the joy of observers and NSInternalInconsistancyException for KVO

2016-05-19 Thread Alex Zavatone
I'm having fun with async NSURLSession downloads but running into objects 
deleting themselves in error cases while still being observed, resulting in the 
lovely NSInternalInconsistancyException.

Is there a means to have an object know when it's being observed so that it 
will refuse to nuke itself in this condition?

Sure, I can set a breakpoint on dealloc to see when this is happening, but I'm 
sure you lots of people have already run into this condition and have already 
figured out how to handle it.

Is there any safer KVO technique to prevent or detect the dreaded "An instance 
of xx was deallocated while key value observers were still registered with 
it"?

Thanks in advance,

Alex Zavatone
___

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 question

2015-11-18 Thread Gerd Knops
One possible issues is that `self.thingy=x;` will trigger two change 
notifications for `thingy`: one for `self.dictionaryOfThings = temp;` (due to 
keyPathsForValuesAffectingThingy), and one when the setter exits. Depending one 
what your observer does this may have unforeseen side effects. 

A possible workaround would be to replace `self.dictionaryOfThings = temp;` 
with `_dictionaryOfThings = temp;`.

Gerd


> 
> On Nov 17, 2015, at 19:18, Graham Cox <graham@bigpond.com> wrote:
> 
> I’m using KVO to observe a bunch of properties.
> 
> Most of these properties are split out into simple things that set a single 
> value, but internal to my object, some end up setting a common dictionary of 
> attributes, which is also a property.
> 
> I KVO observe both the simple properties and the common dictionary property. 
> Mostly this is working, but when code directly sets the dictionary property, 
> the other properties don’t trigger their observers, even though I’m 
> implementing the +keyPathsForValuesAffecting, which I believe 
> should cause the additional triggering. Have I understood that right?
> 
> Here’s the kind of code I have:
> 
> 
> @property (retain) id thingy;
> @property (retain) NSDicitonary* dictionaryOfThings;
> 
> @implementation
> 
> - (void)   setThingy:(is thing
> {
>   NSMutableDictionary* temp = [self.dictionaryOfThings mutableCopy];
>   [temp setObject:thing forKey:kThingKey];
>   self.dictionaryOfThings = temp;
> }
> 
> - (id) thingy
> {
>   return [self.dictionaryOfThings objectForKey:kThingKey];
> }
> 
> 
> + (NSSet*)  keyPathsForValuesAffectingThingy
> {
>   return [NSSet setWithObject:@“dictionaryOfThings”];
> }
> 
> 
> So what I want (expect?) is that is code sets -dictionaryOfThings directly, 
> an observer of ‘thingy’ will be triggered. Is that right?
> 
> 
> —Graham
> 
> 
> 
> ___
> 
> 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/gerti-cocoadev%40bitart.com
> 
> This email sent to gerti-cocoa...@bitart.com


___

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 question

2015-11-18 Thread Ken Thomases
On Nov 17, 2015, at 7:18 PM, Graham Cox <graham@bigpond.com> wrote:
> 
> I’m using KVO to observe a bunch of properties.
> 
> Most of these properties are split out into simple things that set a single 
> value, but internal to my object, some end up setting a common dictionary of 
> attributes, which is also a property.
> 
> I KVO observe both the simple properties and the common dictionary property. 
> Mostly this is working, but when code directly sets the dictionary property, 
> the other properties don’t trigger their observers, even though I’m 
> implementing the +keyPathsForValuesAffecting, which I believe 
> should cause the additional triggering. Have I understood that right?

If by "code directly sets the dictionary property", you mean always in a 
KVO-compliant manner, then yes.


> @property (retain) id thingy;
> @property (retain) NSDicitonary* dictionaryOfThings;

It's not clear if this is a public or private property.  If it's public, and 
probably even if it's private, this should be a "copy" property, not just 
"retain".  If it's just "retain", you're not protected against somebody setting 
it to a mutable dictionary and then subsequently mutating the dictionary, 
thereby effectively mutating your property in a non-KVO-compliant manner.

All of that said, I agree with Quincey.  You should just use either normal 
properties backed by (compiler-synthesized) instance variables, or you can use 
a secondary object with such properties.  Using a dictionary may seem like a 
quick-and-dirty solution, but invites problems in the long run.

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 question

2015-11-18 Thread Alex Zavatone
Are you implying that one KVO is blocking the others?

Sent from my iPhone

> On Nov 17, 2015, at 8:18 PM, Graham Cox <graham@bigpond.com> wrote:
> 
> I’m using KVO to observe a bunch of properties.
> 
> Most of these properties are split out into simple things that set a single 
> value, but internal to my object, some end up setting a common dictionary of 
> attributes, which is also a property.
> 
> I KVO observe both the simple properties and the common dictionary property. 
> Mostly this is working, but when code directly sets the dictionary property, 
> the other properties don’t trigger their observers, even though I’m 
> implementing the +keyPathsForValuesAffecting, which I believe 
> should cause the additional triggering. Have I understood that right?
> 
> Here’s the kind of code I have:
> 
> 
> @property (retain) id thingy;
> @property (retain) NSDicitonary* dictionaryOfThings;
> 
> @implementation
> 
> - (void)   setThingy:(is thing
> {
>NSMutableDictionary* temp = [self.dictionaryOfThings mutableCopy];
>[temp setObject:thing forKey:kThingKey];
>self.dictionaryOfThings = temp;
> }
> 
> - (id) thingy
> {
>return [self.dictionaryOfThings objectForKey:kThingKey];
> }
> 
> 
> + (NSSet*)  keyPathsForValuesAffectingThingy
> {
>return [NSSet setWithObject:@“dictionaryOfThings”];
> }
> 
> 
> So what I want (expect?) is that is code sets -dictionaryOfThings directly, 
> an observer of ‘thingy’ will be triggered. Is that right?
> 
> 
> —Graham
> 
> 
> 
> ___
> 
> 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/zav%40mac.com
> 
> This email sent to z...@mac.com

___

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 question

2015-11-18 Thread Quincey Morris
On Nov 18, 2015, at 16:29 , Roland King <r...@rols.org> wrote:
> 
> I didn’t read his original question as saying that

I could easily have got it wrong, but I believe what he was saying was that 
much of his system was working. The part that doesn’t work is when (e.g.) the 
Font Manager updates the dictionary directly, by which I mean it changes values 
in the dictionary, but does not replace the entire dictionary in the model 
object (it can’t do that, it doesn’t know where to find the model object, or 
what the property name of the dictionary in the model object is).

In this kind of update, Graham is expecting a KVO notification “for the 
dictionary”, in order to trigger 
___

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 question

2015-11-18 Thread Roland King

> On 19 Nov 2015, at 08:38, Quincey Morris 
> <quinceymor...@rivergatesoftware.com> wrote:
> 
> (sorry, posted the incomplete message by accident)
> 
> On Nov 18, 2015, at 16:29 , Roland King <r...@rols.org 
> <mailto:r...@rols.org>> wrote:
>> 
>> I didn’t read his original question as saying that
> 
> I could easily have got it wrong, but I believe what he was saying was that 
> much of his system was working. The part that doesn’t work is when (e.g.) the 
> Font Manager updates the dictionary directly, by which I mean it changes 
> values in the dictionary, but does not replace the entire dictionary in the 
> model object (it can’t do that, it doesn’t know where to find the model 
> object, or what the property name of the dictionary in the model object is).
> 
> In this kind of update, Graham is expecting a KVO notification “for the 
> dictionary”, in order to trigger keyPathsForValuesAffectingThingy. I’m saying 
> that can’t possibly happen.
> 
> 

I agree that if what he’s doing is changing values in the dictionary then he’s 
not going to get a change notification for the dictionary. I just read his 
message again and I can’t read it as saying anything else than the entire 
dictionary is being replaced, perhaps it’s just how I read it. I think we need 
some clarification here about what’s really getting changed. 
___

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 question

2015-11-18 Thread Roland King

> On 19 Nov 2015, at 08:15, Quincey Morris 
> <quinceymor...@rivergatesoftware.com> wrote:
> 
> On Nov 18, 2015, at 14:35 , Graham Cox <graham@bigpond.com> wrote:
>> 
>> it’s just that if other code changes the attributes dictionary (such as the 
>> Font Manager) then I need these split out properties to trigger their 
>> notifications so that the UI shows the change
> 
> I think I understand, finally. No, what you’re doing won’t work.
> 
> The problem is that if (say) the Font Manager has a pointer to your 
> NSMutableDictionary object, and mutates it — sets a new value for a key — 
> there *will* be a KVO notification** — I believe we know that the standard 
> NSMutableDictionary class issues KVO notifications for value changes, though 
> I’m not sure whether it’s documented — but it won’t be a notification for the 
> dictionary***, it will be a notification for the individual key.
> 

I didn’t read his original question as saying that however, that he was 
mutating an individual element of a mutable dictionary property. Grabbing what 
was written

> So what I want (expect?) is that is code sets -dictionaryOfThings directly, 
> an observer of ‘thingy’ will be triggered. Is that right?


which when you look at it doesn’t quite make sense, -dictionaryOfThings is a 
method so you can’t set it so I assumed it meant replacing the whole dictionary 
like so

myObject.dictionaryOfThings = newDictionaryOfNewThings;

or calling

[ myObject setDictionaryOfThings:newDictionaryOfNewThings ];

then the original dependent KVO code as-written should fire, for every property 
which has dictionaryOfThings as a dependent key. 

A bit of clarification about what was meant by ‘code setting 
-dictionaryOfThings directly’ might help. 


___

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 question

2015-11-18 Thread Quincey Morris
(sorry, posted the incomplete message by accident)

On Nov 18, 2015, at 16:29 , Roland King <r...@rols.org <mailto:r...@rols.org>> 
wrote:
> 
> I didn’t read his original question as saying that

I could easily have got it wrong, but I believe what he was saying was that 
much of his system was working. The part that doesn’t work is when (e.g.) the 
Font Manager updates the dictionary directly, by which I mean it changes values 
in the dictionary, but does not replace the entire dictionary in the model 
object (it can’t do that, it doesn’t know where to find the model object, or 
what the property name of the dictionary in the model object is).

In this kind of update, Graham is expecting a KVO notification “for the 
dictionary”, in order to trigger keyPathsForValuesAffectingThingy. I’m saying 
that can’t possibly happen.


___

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 question

2015-11-18 Thread Graham Cox
Hi guys, thanks for your replies - sorry took a while to get back to this, was 
in a long meeting.


Anyway, Quincey, I’m not trying to get notified for mutations to the 
dictionary. The dictionary is being replaced as a single entity wholesale.


The way the font manager works is that for a given attribute change, it asks 
the first responder to send it the dictionary of attributes for the selected 
text. (-changeAttributes:) It then mutates a copy of that dictionary 
(-convertAttributes:) and returns the entire mutated copy. The text view then 
applies that as a single object to the selected text run.

In my case I’ve actually wrapped the text (attributed string) in another object 
that splits out specific text-related properties separately, which makes it 
much easier to bind these properties to particular bits of UI, for example 
changing the Font. That all works - if I set my -font property, internally it 
changes the font attribute in the -textAttributes property, I get notifications 
on both -font and -textAttributes. If I change the text selection, the 
attributes applying to that run trigger notifications for the font property in 
my UI. If some other object (e.g. Font Manager) changes the font using its 
normal mechanism, which updates the -textAttributes property directly, I need 
notifications to be triggered for the -font property. In fact, they are, 
because I have +keyPathsForValuesAffectingFont returning textAttributes.

However this was not working consistently for all properties. I was trying to 
boil it down to generalities hence my dictionaryOfThings and thingy 
terminology, just to clarify that my understanding of KVO was correct. Seems it 
was. So my problem must be something specific in my code because in fact this 
is working for nearly everything, just not all. So if my understanding of KVO 
is correct, I now know where to look for these few missing pieces.


—Graham






> On 19 Nov 2015, at 11:38 AM, Quincey Morris 
> <quinceymor...@rivergatesoftware.com> wrote:
> 
> (sorry, posted the incomplete message by accident)
> 
> On Nov 18, 2015, at 16:29 , Roland King <r...@rols.org> wrote:
>> 
>> I didn’t read his original question as saying that
> 
> I could easily have got it wrong, but I believe what he was saying was that 
> much of his system was working. The part that doesn’t work is when (e.g.) the 
> Font Manager updates the dictionary directly, by which I mean it changes 
> values in the dictionary, but does not replace the entire dictionary in the 
> model object (it can’t do that, it doesn’t know where to find the model 
> object, or what the property name of the dictionary in the model object is).
> 
> In this kind of update, Graham is expecting a KVO notification “for the 
> dictionary”, in order to trigger keyPathsForValuesAffectingThingy. I’m saying 
> that can’t possibly happen.
> 
> 


___

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 question

2015-11-18 Thread Quincey Morris
On Nov 18, 2015, at 14:35 , Graham Cox <graham@bigpond.com> wrote:
> 
> it’s just that if other code changes the attributes dictionary (such as the 
> Font Manager) then I need these split out properties to trigger their 
> notifications so that the UI shows the change

I think I understand, finally. No, what you’re doing won’t work.

The problem is that if (say) the Font Manager has a pointer to your 
NSMutableDictionary object, and mutates it — sets a new value for a key — there 
*will* be a KVO notification** — I believe we know that the standard 
NSMutableDictionary class issues KVO notifications for value changes, though 
I’m not sure whether it’s documented — but it won’t be a notification for the 
dictionary***, it will be a notification for the individual key.

This will have no effect (assuming I’m still on track) because nothing is 
observing the key path that’s getting the notification. Your UI observers are 
watching yourModel.thingy instead, and your keyPathsForValuesAffectingThingy 
doesn’t fire for the reason given above.

What will work (assuming I’m still on track) is to bind your UI elements to 
yourModel.dictionaryOfThings.thingy instead of yourModel.thingy. In that case, 
a Font Manager update to the dictionary will trigger an update that reaches the 
UI.

The hard part comes if you something is observing the dictionary itself (for 
example, to tell the text system to update when the dictionary changes 
externally). A UI element update will trigger a KVC notification on path 
yourModel.dictionaryOfThings.thingy, but *not* on path 
yourModel.dictionaryOfThings, so the dictionary observer won’t fire. But 
there’s nothing in your existing sample code to suggest that anything is 
observing the dictionary like this, except to trigger the model updates on the 
duplicate properties, which aren’t needed in the scheme I’m suggesting.

It’s a while since we’ve discussed KVO vs. NSMutableDictionary on this list, so 
I may be misremembering how this all works. (Ken can probably straighten that 
out.) Even if it doesn’t work this way, if you are in charge of creating the 
NSMutableDictionary initially, you could write a subclass and give it whatever 
KVO notification behavior you want. Otherwise, you might be able to achieve 
your goal by adding another set of observers to the dictionary keys themselves.


** Maybe that should be “would”, not “will”, since you have no observers of 
this. There are no notifications for regular properties unless something is 
observing them. I’m not sure whether NSMutableDictionary issues notifications 
unconditionally or knows what keys are being observed.

***There can’t be a notification for the dictionary itself, because the code 
that’s mutating it doesn’t know what key to use.
___

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 question

2015-11-18 Thread Graham Cox

> On 18 Nov 2015, at 6:43 PM, Quincey Morris 
> <quinceymor...@rivergatesoftware.com> wrote:
> 
> As a matter of principle, I always think using a dictionary as an API to 
> properties is a terrible idea. You’re much better off defining an object that 
> actually has the properties, even if there are a lot of them. That would 
> solve your difficulty here, since you wouldn’t need two ways of getting to 
> the properties. Also, you’d avoid the danger inherent in exposing your 
> mutable backing store (the NSMutableDictionary) to the outside world, always 
> a prescription for trouble.
> 


I completely agree, but in this case the dictionary in question is the 
attributes of NSAttributedString (in a NSTextView), so I don’t have the choice. 
I have split out numerous individual properties from this so that they are easy 
to bind to specific UI, such as a menu for Font, a menu for font face, a text 
field for font size, etc, etc. But ultimately they have to change the 
attributes dictionary. That all works, it’s just that if other code changes the 
attributes dictionary (such as the Font Manager) then I need these split out 
properties to trigger their notifications so that the UI shows the change. The 
dictionary is being changed in a KVO compliant way, because the entire 
dictionary is updated and replaced as a whole - the settings within the 
dictionary are not mutated individually.

—Graham





___

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 question

2015-11-17 Thread Daniel Stenmark
It seems like it *should* work.  Are you sure you don’t have a typo in your 
addObserver: method?  Considering that you’re using the dictionary’s property 
setter, keyPathsForValuesAffecting shouldn’t even be necessary.  When I 
apply KVO, I try to mitigate the potential unsafely of key paths strings by 
using NSStringFromSelector() whenever possible.

[self.foo addObserver:self forKeyPath:NSStringFromSelector(@selector(bar)) 
options:NSKeyValueObservingOptionNew context:NULL];

Dan


On Nov 17, 2015, at 5:18 PM, Graham Cox 
<graham@bigpond.com<mailto:graham@bigpond.com>> wrote:

I’m using KVO to observe a bunch of properties.

Most of these properties are split out into simple things that set a single 
value, but internal to my object, some end up setting a common dictionary of 
attributes, which is also a property.

I KVO observe both the simple properties and the common dictionary property. 
Mostly this is working, but when code directly sets the dictionary property, 
the other properties don’t trigger their observers, even though I’m 
implementing the +keyPathsForValuesAffecting, which I believe should 
cause the additional triggering. Have I understood that right?

Here’s the kind of code I have:


@property (retain) id thingy;
@property (retain) NSDicitonary* dictionaryOfThings;

@implementation

- (void)   setThingy:(is thing
{
NSMutableDictionary* temp = [self.dictionaryOfThings mutableCopy];
[temp setObject:thing forKey:kThingKey];
self.dictionaryOfThings = temp;
}

- (id) thingy
{
return [self.dictionaryOfThings objectForKey:kThingKey];
}


+ (NSSet*)  keyPathsForValuesAffectingThingy
{
return [NSSet setWithObject:@“dictionaryOfThings”];
}


So what I want (expect?) is that is code sets -dictionaryOfThings directly, an 
observer of ‘thingy’ will be triggered. Is that right?


—Graham



___

Cocoa-dev mailing list 
(Cocoa-dev@lists.apple.com<mailto: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<http://lists.apple.com>

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/dstenmark%40opentable.com

This email sent to dstenm...@opentable.com

___

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 question

2015-11-17 Thread Graham Cox
I’m using KVO to observe a bunch of properties.

Most of these properties are split out into simple things that set a single 
value, but internal to my object, some end up setting a common dictionary of 
attributes, which is also a property.

I KVO observe both the simple properties and the common dictionary property. 
Mostly this is working, but when code directly sets the dictionary property, 
the other properties don’t trigger their observers, even though I’m 
implementing the +keyPathsForValuesAffecting, which I believe should 
cause the additional triggering. Have I understood that right?

Here’s the kind of code I have:


@property (retain) id thingy;
@property (retain) NSDicitonary* dictionaryOfThings;

@implementation

- (void)   setThingy:(is thing
{
NSMutableDictionary* temp = [self.dictionaryOfThings mutableCopy];
[temp setObject:thing forKey:kThingKey];
self.dictionaryOfThings = temp;
}

- (id) thingy
{
return [self.dictionaryOfThings objectForKey:kThingKey];
}


+ (NSSet*)  keyPathsForValuesAffectingThingy
{
return [NSSet setWithObject:@“dictionaryOfThings”];
}


So what I want (expect?) is that is code sets -dictionaryOfThings directly, an 
observer of ‘thingy’ will be triggered. Is that right?


—Graham



___

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 question

2015-11-17 Thread Quincey Morris
On Nov 17, 2015, at 17:18 , Graham Cox <graham@bigpond.com> wrote:
> 
> Mostly this is working, but when code directly sets the dictionary property, 
> the other properties don’t trigger their observers, even though I’m 
> implementing the +keyPathsForValuesAffecting, which I believe 
> should cause the additional triggering. Have I understood that right?

It’s not clear. I can’t think of a compelling reason why the other observers 
shouldn’t trigger, but you are doing something a bit weird.

I wonder, also, if you’re always setting the ‘dictionaryOfThings’ property 
KVO-compliantly? In particular, is the instance variable perhaps changed 
initially from nil to an empty dictionary after there are already observers on 
the dictionary path?

As a matter of principle, I always think using a dictionary as an API to 
properties is a terrible idea. You’re much better off defining an object that 
actually has the properties, even if there are a lot of them. That would solve 
your difficulty here, since you wouldn’t need two ways of getting to the 
properties. Also, you’d avoid the danger inherent in exposing your mutable 
backing store (the NSMutableDictionary) to the outside world, always a 
prescription for trouble.

FWIW.


___

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 detection of changes to selection in NSOpenPanel

2015-07-20 Thread Jonathan Taylor
I’ve just noticed a glitch where my custom file preview box in an NSOpenPanel 
works fine on OS X 10.9.5 but does not get updated on 10.8.5. Specifically, I 
declare a dependency of my property on panel.filenames, panel.URL and 
panel.directoryURL (just to see if ANY of them fire), and none of them are 
getting prodded when the user changes the selected file/directory. Does anybody 
know if this is expected behaviour?

I did notice somewhere buried in here:
https://developer.apple.com/library/mac/releasenotes/AppKit/RN-AppKitOlderNotes/#X10_9Notes
that it says (for OS X 10.9)
 Key Value Observation compliance was dramatically increased for public and 
 some private properties of actual, non sandboxed NSOpen and Save panels, 
 including keys affecting other values. For example, if the directory value 
 changes on a save panel, this will cause a KVO notification to be emitted for 
 the URL value as well as the directory value. Sandboxed NSOpen and Save 
 Panels do not have the same level of KVO compliance.

This does make me wonder if I should perhaps not be surprised that my use of 
keyPathsAffectingValueForKey is not going well, although nothing in that 
statement seems to specifically preclude what I am doing from working on 10.8. 
Does anyone know if there’s any hope of my KVO approach working? The 
alternative seems to be to implement a delegate method for 
panelSelectionDidChange. Would that be the sensible way to deal with this, or 
is there a third and better way I should be using?

Cheers
Jonny
___

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 detection of changes to selection in NSOpenPanel

2015-07-20 Thread Kyle Sluder
On Mon, Jul 20, 2015, at 11:13 AM, Jonathan Taylor wrote:
 This does make me wonder if I should perhaps not be surprised that my use
 of keyPathsAffectingValueForKey is not going well, although nothing in
 that statement seems to specifically preclude what I am doing from
 working on 10.8. Does anyone know if there’s any hope of my KVO approach
 working?

No. If a property is not explicitly documented to be KVO-compliant, you
must assume that it isn't.

The alternative seems to be to implement a delegate method for
 panelSelectionDidChange. Would that be the sensible way to deal with
 this, or is there a third and better way I should be using?

It seems pretty straightforward to just implement the delegate method
regardless of OS version.

--Kyle Sluder

___

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

Assuring KVO compliance.

2015-04-07 Thread Alex Zavatone
I've read Apple's docs on assuring KVO/KVC compliance, but in this particular 
situation, I'd appreciate someone explaining what I'm not getting here if it's 
anything obvious.

I think what I'm asking is how to convert code that has a state exposed as a 
(nonatomic, readwrite) property of a typedef-ed enum so that it can be observed 
by KVO.

The code that I've inherited has an enum (not an NSEnum) that represents the 
app's connected state, 0, 1 or 2.

This enum is then typedef-ed and then exposed as a property through @property 
(nonatomic, readwrite) 

This property is within the AppDelegate and is referred to and set throughout 
the app.


enum APP_State {
APP_State_Normal = 0,
APP_State_Expired = 1,
APP_State_Waiting = 2
};
typedef enum APP_State APP_State;

@property (nonatomic, readwrite) APP_State app_idle_state;


So, I want to set up an approach to monitor this state and set a readout 
graphic based upon the state's value. I had assumed that KVO would be the path 
of least overhead and allow a rather self contained little class to handle this 
without any nasty polling.  

Within a new class, I added an observer to the APP_State property on the 
appDelegate and this operates as expected, but adding the KVO will trigger an 
EXC_BAD_ACCESS when attempting to change the app_idle_state enum property 
within another class that accesses that property in the delegate.

Specifically, this:

delegate.app_idle_state = APP_State_Waiting;

Results in this:
Thread1: EXC_BAD_ACCESS (code=1,address = 0x003f8f3)


First of all, I've never seen enum being attempted to be exposed like this 
(would making this an NS_ENUM help?).

Also, I certainly was expecting *something* to go wrong here, but not causing 
bad access exceptions elsewhere when code in another class attempts to set the 
value of the property (since its property was set to readwrite).

Changing the property declaration to atomic seems to be more correct in that we 
don't want any other operation to happen on it, but that doesn't doesn't affect 
whether or not an EXC_BAD_ACCESS.

Or I could be walking down the wrong path entirely and should just poll for the 
value or have a notification of a state change be sent to the monitoring class.


Thoughts?

Thanks in advance, 
Alex Zavatone
___

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: Assuring KVO compliance.

2015-04-07 Thread Quincey Morris
On Apr 7, 2015, at 09:05 , Alex Zavatone z...@mac.com wrote:
 
 Gremlins, I think.

No, something, but not that.

Enums are a C thing, not even Obj-C. They are, for all intents and purposes, an 
int of some size and signedness chosen by the compiler. So, the enum part of 
this is a red herring. The reason that changing the enum definition made a 
difference is, presumably, that it changed the way things were arranged in 
memory, and that by chance caused your actual problem to do something harmless 
instead of harmful.

Your actual error was this:

 delegate.app_idle_state = APP_State_Waiting;

 Thread1: EXC_BAD_ACCESS (code=1,address = 0x003f8f3)

and you were mislead by the word “access” to think this had something to do 
with accessing the property. Actually, EXC_BAD_ACCESS means an invalid pointer 
to memory.

You can’t tell which pointer, exactly, without looking at the backtrace to see 
exactly where execution was at the time of the exception. If it’s in the line 
of code that assigns the app state, the exception probably means that 
‘delegate’ is invalid, not the attempt to change the property.

So, you need to try to make the EXC_BAD_ACCESS happen again, and take a harder 
look at what’s going on at that point, ideally using the debugger at a 
breakpoint on the exception. You may have a memory management error relating to 
the delegate object — delegate object references are often kept unretained, 
which is prone to errors — or a thread safety issue.



___

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: Assuring KVO compliance.

2015-04-07 Thread Roland King

 On 7 Apr 2015, at 23:12, Alex Zavatone z...@mac.com wrote:
 
 To answer my own question, changing the enum to an NSInteger backed NS_Enum 
 resulted in no more bad access exceptions from other chunks of code 
 attempting to change the APP_State property.
 
 typedef NS_ENUM(NSInteger, APP_State) {
APP_State_Normal = 0,
APP_State_Expired = 1,
APP_State_Waiting = 2
 };
 
 Changing the atomicity of the exposed property had no effect on whether the 
 exception was issued or not.
 
 Hope this helps someone.
 
 Alex Zavatone
 

I was just looking at some of my own code because I’m pretty sure I use enums 
all the time in properties which are KVO and observe them and update them, and 
I’ve never once had to mess around with NS_ENUM to make them work. 

And indeed I found 4 examples quite quickly, all of which look very much like 
your original code, a typedef’ed enum used as a property. 

So I really don’t know where your bad accesses were coming from. 

This was all ObjC right ? 

___

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: Assuring KVO compliance.

2015-04-07 Thread Alex Zavatone
To answer my own question, changing the enum to an NSInteger backed NS_Enum 
resulted in no more bad access exceptions from other chunks of code attempting 
to change the APP_State property.

typedef NS_ENUM(NSInteger, APP_State) {
APP_State_Normal = 0,
APP_State_Expired = 1,
APP_State_Waiting = 2
};

Changing the atomicity of the exposed property had no effect on whether the 
exception was issued or not.

Hope this helps someone.

Alex Zavatone



On Apr 7, 2015, at 10:04 AM, Alex Zavatone wrote:

 I've read Apple's docs on assuring KVO/KVC compliance, but in this particular 
 situation, I'd appreciate someone explaining what I'm not getting here if 
 it's anything obvious.
 
 I think what I'm asking is how to convert code that has a state exposed as a 
 (nonatomic, readwrite) property of a typedef-ed enum so that it can be 
 observed by KVO.
 
 The code that I've inherited has an enum (not an NSEnum) that represents the 
 app's connected state, 0, 1 or 2.
 
 This enum is then typedef-ed and then exposed as a property through @property 
 (nonatomic, readwrite) 
 
 This property is within the AppDelegate and is referred to and set throughout 
 the app.
 
 
 enum APP_State {
APP_State_Normal = 0,
APP_State_Expired = 1,
APP_State_Waiting = 2
 };
 typedef enum APP_State APP_State;
 
 @property (nonatomic, readwrite) APP_State app_idle_state;
 
 
 So, I want to set up an approach to monitor this state and set a readout 
 graphic based upon the state's value. I had assumed that KVO would be the 
 path of least overhead and allow a rather self contained little class to 
 handle this without any nasty polling.  
 
 Within a new class, I added an observer to the APP_State property on the 
 appDelegate and this operates as expected, but adding the KVO will trigger an 
 EXC_BAD_ACCESS when attempting to change the app_idle_state enum property 
 within another class that accesses that property in the delegate.
 
 Specifically, this:
 
 delegate.app_idle_state = APP_State_Waiting;
 
 Results in this:
 Thread1: EXC_BAD_ACCESS (code=1,address = 0x003f8f3)
 
 
 First of all, I've never seen enum being attempted to be exposed like this 
 (would making this an NS_ENUM help?).
 
 Also, I certainly was expecting *something* to go wrong here, but not causing 
 bad access exceptions elsewhere when code in another class attempts to set 
 the value of the property (since its property was set to readwrite).
 
 Changing the property declaration to atomic seems to be more correct in that 
 we don't want any other operation to happen on it, but that doesn't doesn't 
 affect whether or not an EXC_BAD_ACCESS.
 
 Or I could be walking down the wrong path entirely and should just poll for 
 the value or have a notification of a state change be sent to the monitoring 
 class.
 
 
 Thoughts?
 
 Thanks in advance, 
 Alex Zavatone
 ___
 
 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/zav%40mac.com
 
 This email sent to z...@mac.com


___

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: Assuring KVO compliance.

2015-04-07 Thread Alex Zavatone
Thanks Roland. 

Yeah, me neither, but this is inherited code where the previous guys obviously 
come from a java background and have done things in a manner I'm not accustomed 
to.  In this project, refactoring properties and methods in many classes 
actually causes Xcode to tell me I'd be better off handling it manually.  Never 
seen that before.

What doesn't sit right on this BAD_ACCESS problem is why did adding an 
observer cause other code to cause an exception and OK, the exception is 
gone, but do I really understand why it's gone and should this change have 
actually fixed it?

I'm assuming that the bad access is on the setting of the property within 
another class.  I'm assuming that the way the enum is declared and exposed is 
where the problem is and that is causing the exception.  Where its value is 
being set is where the debugger stops and tells me the exception is coming from.

What felt really odd to me was that simply adding an observer to a property in 
one class caused other code which set the property to trigger the exception to 
be thrown.  

However…

all of the classes in this iOS project have their ivars defined in their 
interfaces and then properties created for all of them and occasionally 
synthesizing the properties manually.  

I think we all stopped doing this in 2012 and I'm not going to address all of 
this until I know the product better.  

What this leads to though is a case of OK, I'm going to believe the debugger 
and try to make sure I address KVO/KVC compliance on the observed and make sure 
that the property is about to be observed and changed by multiple sources.  

So, I tried what I thought would be good practices.  Make sure the enum is 
backed by modern and KVC compliant approaches even though properties exposed 
through @synthesize should be KVO compliant, in case the way this property is 
exposed isn't.  For example, due to the way the code is set up, what if the 
property being changed isn't the property I think it is, but the ivar instead?

I didn't change the way the property is @synthesized (still manually), I did 
change the property's atomicity to atomic without affecting the error, the only 
changes I did make were to use NS_Enum and declare the enum type as NSInteger.

In fact, a quick test changing the type of the NS_ENUM from NSInteger back to 
int doesn't cause the BAD_ACCESS to reappear.

I hate to mark something this core as I don't know why but it works, but I 
don't know but it works.

Gremlins, I think.

Thanks for taking the time to eyeball this.
Alex Zavatone



On Apr 7, 2015, at 11:32 AM, Roland King wrote:

 
 On 7 Apr 2015, at 23:12, Alex Zavatone z...@mac.com wrote:
 
 To answer my own question, changing the enum to an NSInteger backed NS_Enum 
 resulted in no more bad access exceptions from other chunks of code 
 attempting to change the APP_State property.
 
 typedef NS_ENUM(NSInteger, APP_State) {
APP_State_Normal = 0,
APP_State_Expired = 1,
APP_State_Waiting = 2
 };
 
 Changing the atomicity of the exposed property had no effect on whether the 
 exception was issued or not.
 
 Hope this helps someone.
 
 Alex Zavatone
 
 
 I was just looking at some of my own code because I’m pretty sure I use enums 
 all the time in properties which are KVO and observe them and update them, 
 and I’ve never once had to mess around with NS_ENUM to make them work. 
 
 And indeed I found 4 examples quite quickly, all of which look very much like 
 your original code, a typedef’ed enum used as a property. 
 
 So I really don’t know where your bad accesses were coming from. 
 
 This was all ObjC right ? 
 

___

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: Assuring KVO compliance.

2015-04-07 Thread Jens Alfke

 On Apr 7, 2015, at 7:04 AM, Alex Zavatone z...@mac.com wrote:
 
 The code that I've inherited has an enum (not an NSEnum) that represents the 
 app's connected state, 0, 1 or 2.

There’s no difference. NS_ENUM is just a macro that defines a C enum, but uses 
some newer (C99?) syntax to specify the integer size that the enum should use. 
(Without that, if you just define a plain enum its size will be sizeof(int), 
IIRC.)

 Results in this:
 Thread1: EXC_BAD_ACCESS (code=1,address = 0x003f8f3)

That’s not a useful crash report. All it says is “something accessed an invalid 
memory address. At a bare minimum you should show the top few lines of the 
stack down to your application code.

I wouldn’t expect any sort of problem with a property that’s an enumerated 
type. I’ve done it often, and there are a lot of properties like that in UIKit, 
for example. But without a backtrace there’s no way of knowing why this failed.

 To answer my own question, changing the enum to an NSInteger backed NS_Enum 
 resulted in no more bad access exceptions from other chunks of code 
 attempting to change the APP_State property.

So, all you did was change the integer size of the value and the crash went 
away. This smells rather like there’s a bug lurking elsewhere in the app code 
that just happened to go away because of some slight change in the alignment of 
the value or the code being generated. If I were you I’d back out that change 
and debug what the actual crash is coming from.

—Jens
___

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: Assuring KVO compliance.

2015-04-07 Thread Alex Zavatone

On Apr 7, 2015, at 3:13 PM, Jens Alfke wrote:

 
 On Apr 7, 2015, at 7:04 AM, Alex Zavatone z...@mac.com wrote:
 
 The code that I've inherited has an enum (not an NSEnum) that represents the 
 app's connected state, 0, 1 or 2.
 
 There’s no difference. NS_ENUM is just a macro that defines a C enum, but 
 uses some newer (C99?) syntax to specify the integer size that the enum 
 should use. (Without that, if you just define a plain enum its size will be 
 sizeof(int), IIRC.)
 
 Results in this:
 Thread1: EXC_BAD_ACCESS (code=1,address = 0x003f8f3)
 
 That’s not a useful crash report. All it says is “something accessed an 
 invalid memory address. At a bare minimum you should show the top few lines 
 of the stack down to your application code.
 
 I wouldn’t expect any sort of problem with a property that’s an enumerated 
 type. I’ve done it often, and there are a lot of properties like that in 
 UIKit, for example. But without a backtrace there’s no way of knowing why 
 this failed.

Thanks.  I didn't want to flood the list with extra data, but it appears I 
should have in this case.



 To answer my own question, changing the enum to an NSInteger backed NS_Enum 
 resulted in no more bad access exceptions from other chunks of code 
 attempting to change the APP_State property.
 
 So, all you did was change the integer size of the value and the crash went 
 away. This smells rather like there’s a bug lurking elsewhere in the app code 
 that just happened to go away because of some slight change in the alignment 
 of the value or the code being generated.

Thanks.  That's what I was afraid of.  

 If I were you I’d back out that change and debug what the actual crash is 
 coming from.

With over 100 cases of @catch (NSException *exception) in this project, I think 
you're many times more right than you know.

We've got LOADS of cases of using the appDelegate as a hold-all for most 
everything and the appDelegate is referred to many times in many methods in 
many classes.

Lots of 2011 style interface and @property definition as well where the ivar is 
declared in the interface and then the @property is and then @synthesized.  

Basically, with all that's obviously out of the ordinary here, I'm looking for 
a good strategy to find the most salient path to identifying the issue here and 
refactoring/modernizing as I go along.

The first step, I guess, is recreating the exception in a fresh copy of the 
project.



Thanks much to you and Quincey.  I hope to get more on this to indicate an 
appropriate culprit and path.

Alex Zavatone
___

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

Core Data To-Many Relationship KVO

2015-02-11 Thread Richard Charles
I have a Core Data in-memory store. There is a managed object which uses KVO on 
a to-many relationship property of itself.

When an object at the other end of the relationship is deleted using 
[managedObjectContext deleteObject:object] the KVO change notification is not 
sent right away.

What triggers or will trigger the KVO change notification?

Richard Charles


___

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: Core Data To-Many Relationship KVO

2015-02-11 Thread Roland King

 On 12 Feb 2015, at 07:27, Richard Charles rcharles...@gmail.com wrote:
 
 I have a Core Data in-memory store. There is a managed object which uses KVO 
 on a to-many relationship property of itself.
 
 When an object at the other end of the relationship is deleted using 
 [managedObjectContext deleteObject:object] the KVO change notification is not 
 sent right away.
 
 What triggers or will trigger the KVO change notification?
 
 Richard Charles
 


committing the core data changes removes them from all the relationships and 
fires KVO changes. see propagatesDeletesAtEndOfEvent: and commitPendingChanges. 
In AppKit usually deletes are propagated once around the event loop, in other 
places they won’t propagate until there’s a save or commitPendingChanges: is 
called. 
___

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: Core Data To-Many Relationship KVO

2015-02-11 Thread Richard Charles

 On Feb 11, 2015, at 4:51 PM, Roland King r...@rols.org wrote:
 
 committing the core data changes removes them from all the relationships and 
 fires KVO changes. see propagatesDeletesAtEndOfEvent: and 
 commitPendingChanges. In AppKit usually deletes are propagated once around 
 the event loop, in other places they won’t propagate until there’s a save or 
 commitPendingChanges: is called.


What “event” does propagatesDeletesAtEndOfEvent refer to? An event loop, some 
type of Core Data event? The documentation as I read it is unclear.

Also commitPendingChanges: does not appear to be in any method of the Cocoa 
frameworks.

Richard Charles


___

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: Core Data To-Many Relationship KVO

2015-02-11 Thread Roland King

 On 12 Feb 2015, at 08:27, Richard Charles rcharles...@gmail.com wrote:
 
 
 On Feb 11, 2015, at 4:51 PM, Roland King r...@rols.org wrote:
 
 committing the core data changes removes them from all the relationships and 
 fires KVO changes. see propagatesDeletesAtEndOfEvent: and 
 commitPendingChanges. In AppKit usually deletes are propagated once around 
 the event loop, in other places they won’t propagate until there’s a save or 
 commitPendingChanges: is called.
 
 
 What “event” does propagatesDeletesAtEndOfEvent refer to? An event loop, some 
 type of Core Data event? The documentation as I read it is unclear.

No idea - why don’t you put a breakpoint in your KVO handler and see where it’s 
being called from, my guess would be the end of the event loop. If you want it 
earlier try calling the method to process pending changes, or remove it from 
the relationship yourself as well as deleting it. 

 
 Also commitPendingChanges: does not appear to be in any method of the Cocoa 
 frameworks.

processPendingChanges:, it’s on NSManagedObjectContext

 
 Richard Charles
 


___

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: Core Data To-Many Relationship KVO

2015-02-11 Thread Richard Charles

 On Feb 11, 2015, at 5:36 PM, Roland King r...@rols.org wrote:
 
 processPendingChanges:, it’s on NSManagedObjectContext

That’s what I was looking for.

Thanks for your help.

Richard Charles


___

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

OS X 10.10 KVO default behaviour change when observers not removed

2015-02-07 Thread Jonathan Mitchell
Jens mentioned in a previous thread that he was not quite sure whether to 
always remove observations or not.
This was bugging me. I always did it, though more out of habit than absolute 
conviction.
The code below confirms that not removing the observation prior to deallocating 
the observing object really is toxic.

As shown if linked on OS X 10.9 the code below may run to completion or may 
terminate with an access violation (YMMV).
If the code completes a warning is logged stating that the observed object 
still has registered observers.
When we mutate the observed key path the deallocated instance gets messaged, 
which may or may not be terminal.

If linked on OS X 10.10 then the code never completes.
Either it terminates due to an access violation or it aborts as the previous 
console warning is now a NSInternalInconsistencyException and the thread aborts.

This issue can lurk in code without causing problems if the observed and 
observing objects tend to get deallocated together.
One can easily see how refactoring could cause the observed object to outlive 
its observer and produce instability.

#import Foundation/Foundation.h

@interface MGSObservedObject : NSObject
@property (strong) NSString *name;
@end

@interface MGSObservingObject : NSObject
@end

int main(int argc, const char * argv[]) {
@autoreleasepool {
MGSObservedObject *observedObject = [MGSObservedObject new];
MGSObservingObject *observingObject = [MGSObservingObject new];

[observedObject addObserver:observingObject forKeyPath:@name 
options:0 context:NULL];
observedObject.name = @Laura Palmer;

BOOL removeObservation = NO;
if (removeObservation) {
[observedObject removeObserver:observingObject forKeyPath:@name 
context:NULL];
}

BOOL deallocObservingObject = YES;
if (deallocObservingObject)  {
observingObject = nil;
}

BOOL pokeObservedObject = YES;
if (pokeObservedObject) {
observedObject.name = @Ronette Pulaski; // on 10.9 observer may 
still register change or we may crash, who knows!
}
}
return 0;
}

@implementation MGSObservingObject

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object 
change:(NSDictionary *)change context:(void *)context
{
NSLog(@observed : %@, [object valueForKeyPath:keyPath]);
}

@end


@implementation MGSObservedObject
@end















___

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

Self KVO...

2014-10-09 Thread Randy Widell
I’m not sure I am having a hard time figuring this out and I am just not 
finding anything via Google.  I am writing a NSTextFieldCell subclass and I 
want to recalculate the size whenever the string value changes via a binding.  
What I can’t seem to figure out is how to observe the change.  I could register 
each instance with itself for change notifications, but that just seems like an 
odd way to go about it.  Seems like it should be possible to just override 
setValue:forKeyPath:, but that never seems to be called.

Any suggestions would be welcome.
___

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: Self KVO...

2014-10-09 Thread Ken Thomases
On Oct 9, 2014, at 10:56 PM, Randy Widell randy.wid...@gmail.com wrote:

 I’m not sure I am having a hard time figuring this out and I am just not 
 finding anything via Google.  I am writing a NSTextFieldCell subclass and I 
 want to recalculate the size whenever the string value changes via a binding. 
  What I can’t seem to figure out is how to observe the change.  I could 
 register each instance with itself for change notifications, but that just 
 seems like an odd way to go about it.  Seems like it should be possible to 
 just override setValue:forKeyPath:, but that never seems to be called.

I would expect that the control will call -setObjectValue: on the cell when it 
(the control) receives a new value via the binding.

It may not be the case that the control ever gets -setValue:forKey: when the 
property to which it is bound changes.  That's one possible way for the 
implementation to work, but as least as likely is for the control to have 
-observeValueForKeyPath:… to be called on it because it was using KVO to 
observe the property to which it is bound.

In any case, the cell should be entirely insulated from the way in which the 
control received its new value.  When implementing a cell, you should not need 
to care about bindings or whatever.

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: Self KVO...

2014-10-09 Thread Randy Widell

 On Oct 9, 2014, at 21:13, Ken Thomases k...@codeweavers.com wrote:
 
 On Oct 9, 2014, at 10:56 PM, Randy Widell randy.wid...@gmail.com wrote:
 
 I’m not sure I am having a hard time figuring this out and I am just not 
 finding anything via Google.  I am writing a NSTextFieldCell subclass and I 
 want to recalculate the size whenever the string value changes via a 
 binding.  What I can’t seem to figure out is how to observe the change.  I 
 could register each instance with itself for change notifications, but that 
 just seems like an odd way to go about it.  Seems like it should be possible 
 to just override setValue:forKeyPath:, but that never seems to be called.
 
 I would expect that the control will call -setObjectValue: on the cell when 
 it (the control) receives a new value via the binding.
 
 It may not be the case that the control ever gets -setValue:forKey: when the 
 property to which it is bound changes.  That's one possible way for the 
 implementation to work, but as least as likely is for the control to have 
 -observeValueForKeyPath:… to be called on it because it was using KVO to 
 observe the property to which it is bound.
 
 In any case, the cell should be entirely insulated from the way in which the 
 control received its new value.  When implementing a cell, you should not 
 need to care about bindings or whatever.
 
 Regards,
 Ken
 

Oh, man, thanks.  I knew it had to be something straightforward.  Yeah, the 
whole KVO route seemed like a weird way to go about it.  Went down the wrong 
rabbit hole.  Thanks!
___

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: Extending KVO to scalar struct types?

2014-08-29 Thread Graham Cox

On 29 Aug 2014, at 3:56 pm, Graham Cox graham@bigpond.com wrote:

 You might wonder if I already know the type why this is even useful.


Having given this a lot more thought, I think it's simpler just to break down 
the compound properties into singular ones on the target object. These can be 
derived from the compound ones and using +keyPathsForValuesAffectingKey, it's 
easy to trigger notifications off of these derived properties. Since I only 
have a few of these compound properties, it's not too much work to add derived 
singular properties and design my UI controller around those.

I think the takeaway from the exercise for me is don't use properties returning 
points, sizes or rects if you want to eventually hook these up to a UI.

--Graham



___

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

Extending KVO to scalar struct types?

2014-08-28 Thread Graham Cox
Hi all,

I had an idea that could simplify quite a bit of tedious glue code, but I'm not 
sure if it's feasible.

-[NSObject setValue: forKeyPath:] can take a key path for any property, but not 
for fields of that property if it's a scalar struct type, e.g. 
@myObject.location.x isn't allowed if the 'location' property is NSPoint for 
example, because NSPoint isn't an object.

I was wondering if I could figure out a way to make this work as a 
pre-processing step prior to setting the value. So for example, knowing that I 
want to set a field of a struct property, I could call a special method that 
strips off the last part of the key path, uses the remainder to get the current 
scalar value, and then use the last part of the path to mutate the relevant 
struct field prior to setting it back, again just using the remainder of the 
keyPath.

The problem here is being able to get to the struct's field at runtime given 
its name as a string. Is that even possible? If it is my scheme should work, 
otherwise it's back to the drawing board.

Incidentally am I right in thinking that bindings is able to do this?

--Graham



___

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: Extending KVO to scalar struct types?

2014-08-28 Thread Jens Alfke

 On Aug 28, 2014, at 8:25 PM, Graham Cox graham@bigpond.com wrote:
 
 The problem here is being able to get to the struct's field at runtime given 
 its name as a string. Is that even possible?

Not in C. The closest you can get is the @encode(…) directive, which at 
compile-time evaluates to the type-encoding string of the argument. But that 
only tells you the types of the struct fields, not the names.

You might be able to do this with RTTI in C++; I've never used that.

—Jens

___

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: Extending KVO to scalar struct types?

2014-08-28 Thread Ken Thomases
On Aug 28, 2014, at 10:25 PM, Graham Cox graham@bigpond.com wrote:

 I had an idea that could simplify quite a bit of tedious glue code, but I'm 
 not sure if it's feasible.
 
 -[NSObject setValue: forKeyPath:] can take a key path for any property, but 
 not for fields of that property if it's a scalar struct type, e.g. 
 @myObject.location.x isn't allowed if the 'location' property is NSPoint 
 for example, because NSPoint isn't an object.
 
 I was wondering if I could figure out a way to make this work as a 
 pre-processing step prior to setting the value. So for example, knowing that 
 I want to set a field of a struct property, I could call a special method 
 that strips off the last part of the key path, uses the remainder to get the 
 current scalar value, and then use the last part of the path to mutate the 
 relevant struct field prior to setting it back, again just using the 
 remainder of the keyPath.
 
 The problem here is being able to get to the struct's field at runtime given 
 its name as a string. Is that even possible? If it is my scheme should work, 
 otherwise it's back to the drawing board.
 
 Incidentally am I right in thinking that bindings is able to do this?

Bindings it not able to do this in most cases.

In case you're not aware, certain Core Animation classes have support for this 
sort of thing: Core Animation Programming Guide: Key-Value Coding Extensions – 
Key Path Support for Structures.
https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CoreAnimation_guide/Key-ValueCodingExtensions/Key-ValueCodingExtensions.html#//apple_ref/doc/uid/TP40004514-CH12-SW8

I suspect they use type encoding to interrogate the type of the property (via 
its getter or setter signature, as appropriate) and then support field access 
for certain specific structure types they understand.

I don't know if there's a general way to do it.

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: Extending KVO to scalar struct types?

2014-08-28 Thread Graham Cox

On 29 Aug 2014, at 1:52 pm, Ken Thomases k...@codeweavers.com wrote:

 In case you're not aware, certain Core Animation classes have support for 
 this sort of thing: Core Animation Programming Guide: Key-Value Coding 
 Extensions – Key Path Support for Structures.
 https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CoreAnimation_guide/Key-ValueCodingExtensions/Key-ValueCodingExtensions.html#//apple_ref/doc/uid/TP40004514-CH12-SW8

Ah, that's where I saw it (not bindings)


 I suspect they use type encoding to interrogate the type of the property (via 
 its getter or setter signature, as appropriate) and then support field access 
 for certain specific structure types they understand.


Actually that will work for me. I only need to support size, points and rects 
at the moment, so it's easy enough to use the -objCType to see which one I have 
and then just change the field according to which specific string I pass. A 
category on NSValue will wrap that up neatly enough.

Thanks!

--Graham



___

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: Extending KVO to scalar struct types?

2014-08-28 Thread Quincey Morris
On Aug 28, 2014, at 21:09 , Graham Cox graham@bigpond.com wrote:

 Actually that will work for me. I only need to support size, points and rects 
 at the moment, so it's easy enough to use the -objCType to see which one I 
 have and then just change the field according to which specific string I 
 pass. A category on NSValue will wrap that up neatly enough.

You can get the information you need out of the Obj-C runtime. In the case 
where a key represents an @property (which is the only case I actually use) the 
code looks like this (omitting error checking):

objc_property_t classProperty = class_getProperty (owningClass, 
classPropertyName);
NSString* attributes = @(property_getAttributes (classProperty));
NSArray* components = [attributes componentsSeparatedByString: @,”];

Now you have an array of strings representing property attributes, the first 
character of which is the attribute type. The property type is attribute type 
“T”, and the rest of the string for a struct type has this form:

{struct-tag-name=…

which you can use to figure out what you need.




___

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: Extending KVO to scalar struct types?

2014-08-28 Thread Graham Cox

On 29 Aug 2014, at 3:20 pm, Quincey Morris 
quinceymor...@rivergatesoftware.com wrote:

 {struct-tag-name=…
 
 which you can use to figure out what you need.


This is much what I'm doing, but it's a bit simpler - I don't need to 
introspect the property details of the target object, since I know that 
-valueForKey: will return scalar types wrapped in an NSValue. NSValue has 
-objCType, which for a struct returns {name=...}, e.g. {CGSize=dd}.

I already know that a given property of a given object is a CGSize (say), so 
for those properties I set through my 'unwrapper' method which uses the 
following code in a category on NSValue to do the work:


const char* typ = [self objCType];
NSString* typeString = [NSString stringWithCString:typ 
encoding:NSASCIIStringEncoding];

// split out point, size and rect structs (others not supported at 
present)

if([typeString rangeOfString:@{CGPoint].location == 0)
{
// it's a point

NSPoint p = [self pointValue];

if([fieldName isEqualToString:@x])
p.x = v;
else if([fieldName isEqualToString:@y])
p.y = v;

return [NSValue valueWithPoint:p];
}
else if([typeString rangeOfString:@{CGSize].location == 0)
{
// it's a size

NSSize s = [self sizeValue];

if([fieldName isEqualToString:@width])
s.width = v;
else if ([fieldName isEqualToString:@height])
s.height = v;

return [NSValue valueWithSize:s];
}
else if([typeString rangeOfString:@{CGRect].location == 0)
{
... more


This isn't general, but it covers the common cases of Points, Sizes and Rects, 
which is all I need at present.

The higher level unwrapper splits up the keypath name so that the last 
component is the struct field name, which it passes into this code. The NSValue 
itself is returned by -valueForKeypath: on the target object using the rest of 
the path (i.e. the last component is removed). For specific objects this could 
be done in an override of -setValueForKeyPath, but I'm actually implementing 
this in the controller rather than try and subvert the more general KVC 
mechanics - seems a bit safer that way.

Works nicely for my use case :)

--Graham



___

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: Extending KVO to scalar struct types?

2014-08-28 Thread Graham Cox

On 29 Aug 2014, at 3:48 pm, Graham Cox graham@bigpond.com wrote:

 I already know that a given property of a given object is a CGSize (say)


You might wonder if I already know the type why this is even useful.

In a UI, different controls might set values independenty such as the x and y 
of a point. Each control is actually setting the same property (a point), but 
driving separate parts of it (the x and y). The UI controller is simplified if 
it can treat compound properties as if they were a single value, e.g. 
location.x, location.y, otherwise every time I set x, I have to go and fetch y 
as well and set both together (in reality that's still what I'm doing, but the 
very high level code that responds to the control doesn't need to know about it 
- it can just call my unwrapper with a keypath extended to include the field). 
Since I have hundreds of properties driven by UI this way (including multiple 
values across an array of objects), it's a big saving to genericise it.

--Graham



___

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

null value in KVO change dictionary ?

2014-08-22 Thread Luc Van Bogaert
Hello,

I'm puzzled by a problem that I am seeing with key value observing an 
arraycontroller and I'm hoping that someone here could shed some light. Here's 
the situation:

I have a nib with a panel that contains a collectionview and an 
arraycontroller. It's like some Tool panel in a drawing app. The 
arraycontroller content binding is bound to a method in the windowcontroller 
(file's owner) that returns an array of custom objects. The collectionview 
content and selectionIndexes bindings are bound to the arraycontroller. This 
all seems to play nicely together.

Next, the windowcontroller's document is observing the 'selection' property of 
the arraycontroller. The purpose is to get hold of whatever object is selected 
in the collectionview and link that to a 'tool' property of the document. Now, 
when I change the selection in the collectionview, the document is indeed 
notified, but what's puzzling me is that the value for the 'new' key in the 
change dictionary is 'null'. 

I've tried observing other arraycontroller properties, such as 
'selectionIndexes' or 'selectedObjects', and the document gets all the 
notifications, but 'new' as well as 'old' value in the change dictionary are 
always 'null', even though I can get a hold of the selected object using 
'[object selectedObjects]'. So why is this object not in the change dictionary? 

Thanks for any help.
-- 
Luc Van Bogaert



smime.p7s
Description: S/MIME cryptographic signature
___

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: null value in KVO change dictionary ?

2014-08-22 Thread Ken Thomases
On Aug 22, 2014, at 4:31 PM, Luc Van Bogaert luc.van.boga...@me.com wrote:

 I'm puzzled by a problem that I am seeing with key value observing an 
 arraycontroller and I'm hoping that someone here could shed some light.

 I've tried observing other arraycontroller properties, such as 
 'selectionIndexes' or 'selectedObjects', and the document gets all the 
 notifications, but 'new' as well as 'old' value in the change dictionary are 
 always 'null', even though I can get a hold of the selected object using 
 '[object selectedObjects]'. So why is this object not in the change 
 dictionary? 

This is a long-standing issue with array controllers.  The KVO change 
notifications never include the new or old values, regardless of the KVO 
options to request them.  You just have to query the object via the key path to 
get the new value.  If you request NSKeyValueObservingOptionPrior, you can get 
the old value at the time that fires.

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

How can an instance KVO its own and super's attributes, especially with overrides?

2014-08-20 Thread Daryle Walker
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? Without causing infinite 
recursion if I override an attribute I’m watching? Here’s my header:

 @interface PrBulkFileOperation : NSOperation
 
 +(instancetype)openFiles:(NSArray *)paths application:(NSApplication *)app;
 
 @property (readonly) NSArray *files;  // Elements are NSURL*
 @property (readonly) NSApplication *  application;
 
 @end


And the applicable source:

 @interface PrBulkFileOperation () {
 NSArray *  _files;
 NSApplication *  _app;
 
 NSMutableSet  *_cancelledFiles, *_failedFiles, *_successfulFiles;
 
 NSMutableDictionary *  _fileFromBrowser;
 }
 
 @property (readonly) NSSet *cancelledFiles, *failedFiles, *successfulFiles;
 @property (readonly) NSMutableSet *mutableCancelledFiles, 
 *mutableFailedFiles, *mutableSuccessfulFiles;
 
 @property NSMutableDictionary *  fileFromBrowser;
 
 - (instancetype)initWithFiles:(NSArray *)paths application:(NSApplication 
 *)app;
 
 @end
 
 @implementation PrBulkFileOperation
 
 #pragma mark Property getters  setters
 
 @synthesize files;
 
 @synthesize application = _app;
 
 @synthesize cancelledFiles  = _cancelledFiles;
 @synthesize failedFiles = _failedFiles;
 @synthesize successfulFiles = _successfulFiles;
 @synthesize fileFromBrowser = _fileFromBrowser;
 
 - (void)addCancelledFilesObject:(NSURL *)file {
 [_cancelledFiles addObject:file];
 }
 
 - (void)removeCancelledFilesObject:(NSURL *)file {
 [_cancelledFiles removeObject:file];
 }
 
 - (NSMutableSet *)mutableCancelledFiles {
 return [self mutableSetValueForKey:@cancelledFiles];
 }
 
 - (void)addFailedFilesObject:(NSURL *)file {
 [_failedFiles addObject:file];
 }
 
 - (void)removeFailedFilesObject:(NSURL *)file {
 [_failedFiles removeObject:file];
 }
 
 - (NSMutableSet *)mutableFailedFiles {
 return [self mutableSetValueForKey:@failedFiles];
 }
 
 - (void)addSuccessfulFilesObject:(NSURL *)file {
 [_successfulFiles addObject:file];
 }
 
 - (void)removeSuccessfulFilesObject:(NSURL *)file {
 [_successfulFiles removeObject:file];
 }
 
 - (NSMutableSet *)mutableSuccessfulFiles {
 return [self mutableSetValueForKey:@successfulFiles];
 }
 
 #pragma mark KVO management
 
 + (NSSet *)keyPathsForValuesAffectingIsReady {
 return [NSSet setWithObjects:@super.isReady, @cancelledFiles, 
 @failedFiles, @successfulFiles, nil];
 }
 
 #pragma mark Conventional overrides
 
 - (BOOL)isReady {
 return [super isReady]  (self.cancelledFiles.count + 
 self.failedFiles.count + self.successfulFiles.count = files.count);
 }
 
 @end

Are my key paths for my own attributes correct? Can I point to an attribute 
from super with “super.whatever”? Can I really trigger my ready flag with just 
indirect observations on the four attributes I need?

— 
Daryle Walker
Mac, Internet, and Video Game Junkie
darylew AT mac DOT com 

___

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: How can an instance KVO its own and super's attributes, especially with overrides?

2014-08-20 Thread Ken Thomases
On Aug 20, 2014, at 11:02 PM, Daryle Walker dary...@mac.com 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 (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

When would I use this (im)mutable property pair setup? (Misunderstanding advanced KVO)

2014-08-15 Thread Daryle Walker
As I’m stripping out the NSDocument stuff, I realize that I need some sort of 
global object to hold each window(-controller) as I create them, otherwise ARC 
will purge them soon after creation.  The application delegate seems like a 
good option, as it’s my only other custom class and Apple uses it to store the 
window in sample projects with a single window.  I read a neat technique at 
http://eschatologist.net/blog/?p=189, and I’m wondering if I would ever need 
it and should switch to something easier.

//==In the header file===
@interface PrairieAppDelegate : NSObject NSApplicationDelegate, 
NSOpenSavePanelDelegate

// unrelated declarations...

@property (nonatomic, copy) NSSet * windowControllers;
@property (nonatomic, readonly) NSMutableSet *  mutableWindowControllers;

@end

//=

I put the implementation methods in the source file:

//==In the implementation file===
#pragma mark Private interface

@interface PrairieAppDelegate () {
NSMutableSet *  _windowControllers;
}

@end

@implementation PrairieAppDelegate

#pragma mark Initialization

- (id)init
{
if (self = [super init]) {
_windowControllers = [[NSMutableSet alloc] init];
}
return self;
}

// No explicit dealloc.

#pragma mark Property getters  setters

// trim unrelated property accessors...

- (NSSet *)windowControllers
{
return [NSSet setWithSet:_windowControllers];
}

- (void)setWindowControllers:(NSSet *)windowControllers
{
[_windowControllers setSet:windowControllers];
}

- (void)addWindowControllersObject:(PrBrowserController *)controller
{
[_windowControllers addObject:controller];
}

- (void)addWindowControllers:(NSSet *)controllers
{
[_windowControllers unionSet:controllers];
}

- (void)removeWindowControllersObject:(PrBrowserController *)controller
{
[_windowControllers removeObject:controller];
}

- (void)removeWindowControllers:(NSSet *)controllers
{
[_windowControllers minusSet:controllers];
}

- (void)intersectWindowControllers:(NSSet *)controllers
{
[_windowControllers intersectSet:controllers];
}

@synthesize mutableWindowControllers = _windowControllers;

#pragma mark NSApplicationDelegate overrides
//…

//=

My window-controller class instances put themselves in the set on “init” and 
remove themselves on “dealloc”.  I originally had “mutableWindowControllers 
private to the implementation file, but the window-controller instances 
couldn’t insert themselves with only “windowControllers public.  That makes 
sense if I had an actual NSSet; but then what are these mutator methods 
actually supposed to do?  When would they ever be called?  Do I have to move 
them to the header file?

Should I get rid of them and stick to just a mutable-set property?  (Delete the 
current “windowControllers” and rename the mutable variant.)  But the text 
seemed like that would mess up KVO in a different way.

— 
Daryle Walker
Mac, Internet, and Video Game Junkie
darylew AT mac DOT com 

___

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: When would I use this (im)mutable property pair setup? (Misunderstanding advanced KVO)

2014-08-15 Thread Quincey Morris
(reposted for formatting)

On Aug 15, 2014, at 16:24 , Daryle Walker dary...@mac.com wrote:

 As I’m stripping out the NSDocument stuff, I realize that I need some sort of 
 global object to hold each window(-controller) as I create them, otherwise 
 ARC will purge them soon after creation.  The application delegate seems like 
 a good option, as it’s my only other custom class and Apple uses it to store 
 the window in sample projects with a single window.  I read a neat technique 
 at http://eschatologist.net/blog/?p=189, and I’m wondering if I would ever 
 need it and should switch to something easier.

It’s the right idea, but the wrong implementation.

 @property (nonatomic, copy) NSSet * windowControllers;
 @property (nonatomic, readonly) NSMutableSet *  mutableWindowControllers;

Make the “windowControllers” property ‘readonly’ too. Although it’s feasible to 
allow the entire set to be changed via the setter, there are other ways to do 
this (e.g. removeAll + add), and you’re unlikely to need to do that anyway. The 
‘copy’ property “pretends” that the implementation is something other than it 
is.

 - (NSSet *)windowControllers
 {
return [NSSet setWithSet:_windowControllers];
 }

It’s simpler to ‘return _windowControllers;’. Or, better, use ‘@synthesize 
windowControllers = _mutableWindowControllers;'

Since the return value is type ‘NSSet*’, the client can’t use the pointer to 
mutate the collection. (You can typically assume the client won’t do something 
hacky, like cast the pointer back to a NSMutableSet*. If you can’t assume that, 
you’ve got bigger problems.)

 - (void)setWindowControllers:(NSSet *)windowControllers
 {
[_windowControllers setSet:windowControllers];
 }
 
 You don’t need this, if you make the “windowControllers” property ‘readonly’, 
 as I recommended above.
 
 - (void)addWindowControllersObject:(PrBrowserController *)controller
 {
[_windowControllers addObject:controller];
 }
 
 - (void)addWindowControllers:(NSSet *)controllers
 {
[_windowControllers unionSet:controllers];
 }
 
 - (void)removeWindowControllersObject:(PrBrowserController *)controller
 {
[_windowControllers removeObject:controller];
 }
 
 - (void)removeWindowControllers:(NSSet *)controllers
 {
[_windowControllers minusSet:controllers];
 }

These are correct, though you only need one of the ‘add…’ and one of the 
‘remove…’ methods. Although it’s not wrong to implement both of each, it’s 
overkill for a set that’s not going to be very large. It’s typical to implement 
only the 1st and 3rd of these. (Keep in mind, you’re unlikely to want to add a 
*set* of window controllers at once.)

Note that these are the KVC “mutable unordered accessors” described here:


https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/KeyValueCoding/Articles/AccessorConventions.html

This means it’s safe to expose these methods publicly. Or you can keep them 
private, and let clients use “mutableWindowControllers” for all their mutation 
needs. This is a matter of taste only.

 - (void)intersectWindowControllers:(NSSet *)controllers
 {
[_windowControllers intersectSet:controllers];
 }

No, you don’t need this, or any other accessors. If you do everything else 
right, any client invocation of (say) ‘[myAppDelegate.mutableWindowControllers 
intersectSet: controllers];’ will get automatically translated into a 
combination of ‘add…’ and ‘remove…’ methods *and will be KVO-compliant*. Your 
code isn’t KVO compliant.

 @synthesize mutableWindowControllers = _windowControllers;

No, this is wrong and dangerous. You’re handing out a mutable reference to your 
private ivar, thus allowing clients to run rampant on your property’s integrity.

Instead, you should implement it like this:

- (NSMutableSet*) mutableWindowControllers {
return [self mutableSetValueForKey: “windowControllers”];
}

This returns a proxy object, so your underlying set stays private, and any 
mutation that a client applies to the proxy is actually applied to your 
underlying data via your accessors (the ‘add…’ and ‘remove…’ methods) *and* is 
KVO compliant.

Finally, my preference is to use a NSArray metaphor for this sort of thing, 
rather than a NSSet metaphor. Yes, the collection of window controllers is 
unordered, but NSSet uses ‘isEqual:’ equality rather than pointer equality to 
distinguish between members. By default, it’s the same thing, but the reliance 
on *not* having a customized ‘isEqual:’ for your window controller classes is a 
hidden fragility in your implementation.

Again, because you’re not going to have a very big collection of window 
controllers, performance and efficiency of the underlying (set vs array) 
representation is not a significant issue.


___

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

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

viewDidLoad and KVO

2014-06-05 Thread Rick Mann
I often have a view controller that displays a view associated with a model 
object. So, I'll have a foo property on that VC, and in the prepareForSegue 
call that presents the VC, I'll setFoo on it.

In my -setFoo: method, I set up KVO on the properties of the foo that I'm 
interested in displaying. In the -observe... method, I update the various bits 
of UI as properties change.

This generally works very well, except when I get to the VC via a segue. 
-prepareForSegue gets called before -viewDidLoad, so none of the IBOutlets 
exist yet.

I can solve this by doing an explicit UI update step in -viewDidLoad, but that 
ends up effectively duplicating the UI update code.

I can load the view in -setFoo: by referencing self.view, but this seems like a 
hack.

What are other people doing to address this? Any best practice you guys like?

-- 
Rick




___

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: viewDidLoad and KVO

2014-06-05 Thread Lee Ann Rucker
 In my -setFoo: method, I set up KVO on the properties of the foo that I'm 
 interested in displaying. In the -observe... method, I update the various 
 bits of UI as properties change.

If you're doing something like this:

- (void)setFoo: (Foo *)aFoo
{
  [foo removeObserver:self forKeyPath:@whatever...];
  foo = aFoo;
  [foo addObserver:self forKeyPath:@whatever...;
}

we used that pattern for a while but were constantly getting bit by observers 
on objects being dealloced or KVO firing and triggering unwanted side effects 
if we called setFoo: in dealloc. So we did a complete switch over to doing

 [self addObserver:self forKeyPath:@foo.whatever...

in init, and removeObserver in dealloc, because you can remove an observer on 
yourself in dealloc without the observers still registered warning.

Since it's on self, you can set it before foo exists, and setFoo: triggers it. 
Plus we could use synthesized setters.

- Original Message -
From: Rick Mann rm...@latencyzero.com
To: Cocoa Developers cocoa-dev@lists.apple.com
Sent: Wednesday, June 4, 2014 10:03:20 PM
Subject: viewDidLoad and KVO

I often have a view controller that displays a view associated with a model 
object. So, I'll have a foo property on that VC, and in the prepareForSegue 
call that presents the VC, I'll setFoo on it.

In my -setFoo: method, I set up KVO on the properties of the foo that I'm 
interested in displaying. In the -observe... method, I update the various bits 
of UI as properties change.

This generally works very well, except when I get to the VC via a segue. 
-prepareForSegue gets called before -viewDidLoad, so none of the IBOutlets 
exist yet.

I can solve this by doing an explicit UI update step in -viewDidLoad, but that 
ends up effectively duplicating the UI update code.

I can load the view in -setFoo: by referencing self.view, but this seems like a 
hack.

What are other people doing to address this? Any best practice you guys like?

-- 
Rick




___

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://urldefense.proofpoint.com/v1/url?u=https://lists.apple.com/mailman/options/cocoa-dev/lrucker%2540vmware.comk=oIvRg1%2BdGAgOoM1BIlLLqw%3D%3D%0Ar=yJFJhaNnTZDfFSSz1U9TSNMmxGyib3KjZGuKfIhHLxA%3D%0Am=qYOnOaiiYwn8zuydsyBcZuhg6AnT0QTIlKRcBpdwfnM%3D%0As=a80229e6e590ffa9a96606cdc929d245804adff0b0a29bb275a85110c02b83bb

This email sent to lruc...@vmware.com
___

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: viewDidLoad and KVO

2014-06-05 Thread Rick Mann

On Jun 5, 2014, at 00:26 , Lee Ann Rucker lruc...@vmware.com wrote:

 If you're doing something like this:
 
 - (void)setFoo: (Foo *)aFoo
 {
  [foo removeObserver:self forKeyPath:@whatever...];
  foo = aFoo;
  [foo addObserver:self forKeyPath:@whatever...;
 }
 
 we used that pattern for a while but were constantly getting bit by observers 
 on objects being dealloced or KVO firing and triggering unwanted side effects 
 if we called setFoo: in dealloc. So we did a complete switch over to doing
 
 [self addObserver:self forKeyPath:@foo.whatever...
 
 in init, and removeObserver in dealloc, because you can remove an observer on 
 yourself in dealloc without the observers still registered warning.
 
 Since it's on self, you can set it before foo exists, and setFoo: triggers 
 it. Plus we could use synthesized setters.

I collect the removeObserver calls into an ignoreFoo method, and similarly 
the addObserver in an observeFoo method. Then in -dealloc I call -ignoreFoo. 
I've never run into the (annoying) registration mismatch errors.

Your suggestion is a good one, but I don't think it solves the problem I have 
of -setFoo: being called before -viewDidLoad (before the IBOutlets are non-nil).

-- 
Rick




___

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: viewDidLoad and KVO

2014-06-05 Thread Alejandro Visiedo García
Why don't you use viewWillAppear and viewDidDisappear, to register and 
unregister observers to your foo property object?

If you don't use ARC, be carefull to unregister on dealloc too!

 El 05/06/2014, a las 09:30, Rick Mann rm...@latencyzero.com escribió:
 
 
 On Jun 5, 2014, at 00:26 , Lee Ann Rucker lruc...@vmware.com wrote:
 
 If you're doing something like this:
 
 - (void)setFoo: (Foo *)aFoo
 {
 [foo removeObserver:self forKeyPath:@whatever...];
 foo = aFoo;
 [foo addObserver:self forKeyPath:@whatever...;
 }
 
 we used that pattern for a while but were constantly getting bit by 
 observers on objects being dealloced or KVO firing and triggering unwanted 
 side effects if we called setFoo: in dealloc. So we did a complete switch 
 over to doing
 
 [self addObserver:self forKeyPath:@foo.whatever...
 
 in init, and removeObserver in dealloc, because you can remove an observer 
 on yourself in dealloc without the observers still registered warning.
 
 Since it's on self, you can set it before foo exists, and setFoo: triggers 
 it. Plus we could use synthesized setters.
 
 I collect the removeObserver calls into an ignoreFoo method, and similarly 
 the addObserver in an observeFoo method. Then in -dealloc I call 
 -ignoreFoo. I've never run into the (annoying) registration mismatch errors.
 
 Your suggestion is a good one, but I don't think it solves the problem I have 
 of -setFoo: being called before -viewDidLoad (before the IBOutlets are 
 non-nil).
 
 -- 
 Rick
 
 
 
 
 ___
 
 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/alejandro.visiedo%40gmail.com
 
 This email sent to alejandro.visi...@gmail.com

___

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

  1   2   3   4   5   6   7   >