Re: Detecting Managed Object Property Change From Undo Redo

2015-01-27 Thread Quincey Morris
On Jan 27, 2015, at 17:21 , Jerry Krinock  wrote:
> 
> Compiler does *not* warn if you have a custom primitive setter without a 
> getter.

FWIW, the compiler doesn’t warn you if you have any setter without a getter.

> I also tried to get it to compile without declaring the instance variable 
> that I access in the custom accessors, by just declaring the property, but 
> that did not work.  To compile, I was required to declare the instance 
> variable in the @interface{…}.

I think it’s just that you’re expecting it to be special, but it isn’t. If you 
want this custom primitive getter:

- (…) primitiveX {…}

and you want the synthesized instance variable, you’d need to declare the 
property:

@property … primitiveX;

and the ivar’s name would be ‘_primitiveX’, not ‘x’ as you tried earlier. Core 
Data isn’t on the compiler’s radar.

___

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: Detecting Managed Object Property Change From Undo Redo

2015-01-27 Thread Jerry Krinock

> On 2015 Jan 27, at 12:44, Keary Suska  wrote:
> 
> What exactly happened when you specified the setter, but not the getter?

I said I wasn’t sure because the project has a bunch of warnings due to ongoing 
major rework, but I just retested again.  Answer: Compiler does *not* warn if 
you have a custom primitive setter without a getter.

I also tried to get it to compile without declaring the instance variable that 
I access in the custom accessors, by just declaring the property, but that did 
not work.  To compile, I was required to declare the instance variable in the 
@interface{…}.



___

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: Detecting Managed Object Property Change From Undo Redo

2015-01-27 Thread Richard Charles

> On Jan 27, 2015, at 1:34 PM, Quincey Morris 
>  wrote:
> 
> FWIW, there is yet another way to get to backing store from a custom 
> primitive accessor — define another, private, Core Data property, and use 
> *its* primitive accessors. This may seem clunky, but it’s officially 
> countenanced in the Core Data Programming Guide, in the "Non-Standard 
> Persistent Attributes” section.
> 
> One advantage of this approach is that you can be sure there are no KVO 
> observers of the private property, so you can gleefully ignore KVO compliance 
> issues when doing housekeeping on the backing store value. Whether this makes 
> Core Data undo easier or harder is one of those things that I’m doomed never 
> to find out.

Thanks for the info. Right now I am trying to simplify a managed object 
subclass and replace non-standard attributes with standard ones without 
sacrificing performance. But this may come in handy sometime down the road. 

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: Detecting Managed Object Property Change From Undo Redo

2015-01-27 Thread Richard Charles

> On Jan 27, 2015, at 1:34 PM, Quincey Morris 
>  wrote:
> 
> On Jan 27, 2015, at 11:06 , Richard Charles  wrote:
>> 
>> That is a key-value coding method. 
> 
> It’s not, as Kyle just said.

Okay, you both win. It is a method which supports key-value coding.

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: Detecting Managed Object Property Change From Undo Redo

2015-01-27 Thread Quincey Morris
On Jan 27, 2015, at 12:44 , Keary Suska  wrote:
> 
> That part of the conversation was private between you and Quincey. I am 
> simply curious as I can't imagine why one would want to. 

It wasn’t intentionally private. It was just one of those cases where a post 
with a lot of invisible formatting got put on moderator hold for size. I was 
too lazy to repost, because Jerry had already quoted the relevant parts.

Jerry didn’t *want* to omit the getter. He just want to try something quickly 
with the setter, and didn’t realize it was going to come unstuck.



___

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: Detecting Managed Object Property Change From Undo Redo

2015-01-27 Thread Keary Suska
On Jan 27, 2015, at 9:52 AM, Jerry Krinock  wrote:

> 
>> On 2015 Jan 27, at 06:46, Keary Suska  wrote:
>> 
>> Better, however, to have a property declaration, which would also synthesize 
>> an ivar in modern LLVMs (as of Xcode 5?).
> 
> You mean the property declaration would synthesize the ivar.  I didn’t try 
> that.  I agree it would be better.

I should clarify that an ivar may not be synthesized if @dynamic is used. I 
forget what the current implementation does for CD, which is a special case. 
Specifying an ivar is probably the best and easiest approach.

>> If we stop and think a moment, why would calling super ever work? This is 
>> still Objective-C, and calling super is only valid when the class' 
>> superclass implements the method. And I bet NSManagedObject doesn't…
> 
> Indeed, it crashed when I invoked it.

Also, more specifically, it is not an override but specifying an implementation 
that, if not provided, will be provided at run-time.

>> Primitive methods … There is absolutely nothing magical about them, because 
>> they need to be entirely un-magical to escape CD's notice.
> 
> 
>> Therefore it is really hard to break anything unless you deliberately do so 
>> (or deliberately ignore compiler warnings).
> 
> I don’t think it warned me about defining a primitive setter without a 
> primitive getter, although it might have because I tried it in a project that 
> is currently giving me 60 warnings due to major work in progress

What exactly happened when you specified the setter, but not the getter? That 
part of the conversation was private between you and Quincey. I am simply 
curious as I can't imagine why one would want to. I would have thought that the 
runtime would have happily provided its own implementation, but since it would 
use the internal store and not the ivar the values won't match. I imagine some 
sort of inconsistency exception could happen...

Keary Suska
Esoteritech, Inc.
"Demystifying technology for your home or business"


___

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: Detecting Managed Object Property Change From Undo Redo

2015-01-27 Thread Quincey Morris
On Jan 27, 2015, at 11:06 , Richard Charles  wrote:
> 
> That is a key-value coding method. 

It’s not, as Kyle just said.

FWIW, there is yet another way to get to backing store from a custom primitive 
accessor — define another, private, Core Data property, and use *its* primitive 
accessors. This may seem clunky, but it’s officially countenanced in the Core 
Data Programming Guide, in the "Non-Standard Persistent Attributes” section.

One advantage of this approach is that you can be sure there are no KVO 
observers of the private property, so you can gleefully ignore KVO compliance 
issues when doing housekeeping on the backing store value. Whether this makes 
Core Data undo easier or harder is one of those things that I’m doomed never to 
find out.



___

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: Detecting Managed Object Property Change From Undo Redo

2015-01-27 Thread Kyle Sluder
On Tue, Jan 27, 2015, at 01:06 PM, Richard Charles wrote:
> 
> > On Jan 27, 2015, at 11:28 AM, Kyle Sluder  wrote:
> > 
> > Historically, I've not been a big Core Data user, but does
> > -[NSManagedObject setPrimitiveValue:forKey:] not do what you want?
> 
> That is a key-value coding method.

No it's not. -setValue:forKey: is a key-value coding method.
-setPrimitiveValue:forKey: is specific to Core Data, and is rather
thoroughly documented as such in the NSManagedObject documentation.

--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

Re: Detecting Managed Object Property Change From Undo Redo

2015-01-27 Thread Richard Charles

> On Jan 27, 2015, at 11:28 AM, Kyle Sluder  wrote:
> 
> Historically, I've not been a big Core Data user, but does
> -[NSManagedObject setPrimitiveValue:forKey:] not do what you want?

That is a key-value coding method. If I remember correctly, key-value coding 
does not bypass existing accessor methods, if they exist. My guess it that 
these methods eventually call the appropriate primitive accessor to access the 
backing store. If the primitive accessor is implemented dynamically then that 
method would be called. If the primitive accessor is implemented by the 
subclass then that method would be called. If the modeled property is defined 
as a ivar and no primitive assessor is implemented by the subclass then the 
frameworks would attempt to set the ivar directly.

I have not used key-value coding much in my managed object subclasses but in 
this instance I don’t think it would 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

Re: Detecting Managed Object Property Change From Undo Redo

2015-01-27 Thread Kyle Sluder
On Tue, Jan 27, 2015, at 12:21 PM, Richard Charles wrote:
> You can’t override a primitive accessor because one is dynamically
> generated for you at runtime if it is needed. If a custom primitive
> accessor is implemented then the managed object subclass must provide an
> ivar for backing storage. The custom primitive accessor can’t use Apple’s
> backing store because the private internal store used by Core Data for
> managed objects is not exposed.

Historically, I've not been a big Core Data user, but does
-[NSManagedObject setPrimitiveValue:forKey:] not do what you want?

--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

Re: Detecting Managed Object Property Change From Undo Redo

2015-01-27 Thread Richard Charles

> On Jan 27, 2015, at 2:24 AM, Quincey Morris 
>  wrote:
> 
> Clearly, all this customization takes some coordination between steps 1 and 
> 2, even if it’s just to know which of them needs to be customized in any 
> particular case, and how. That where the documentation falls down — it gives 
> recipes for a couple of scenarios, without helping you understand how to 
> figure out other scenarios.

I tried really hard to get Core Data to work out of the box for this 
application but ran into the following difficulties:

1. Support for scalars (including C structs).

2. With large data sets KVO can be really slow.

In attempting to work around and work with these issues I discovered that 
during undo/redo only the primitive accessor is called. I also discovered a lot 
of other things. Also as Mike Abdullah pointed out Core Data *does* fire KVO 
notifications during undo/redo. It just doesn’t do it inside the primitive 
accessor.

This whole primitive/public accessor thing can be very confusing. As Quincey 
Morris pointed out the purpose of the primitive accessor is to provide access 
to the private internal backing store of the managed object. This is an 
“Associative Storage” design pattern. (Refer to Cocoa Design Patterns by Buck 
and Yacktman.) Keary Suska also points out another reason for the primitive 
accessor is for setting an objects values without causing KVO or change 
notifications to be sent.

You can’t override a primitive accessor because one is dynamically generated 
for you at runtime if it is needed. If a custom primitive accessor is 
implemented then the managed object subclass must provide an ivar for backing 
storage. The custom primitive accessor can’t use Apple’s backing store because 
the private internal store used by Core Data for managed objects is not exposed.

Primitive accessors are not mandatory. In fact Core Data does *not* dynamically 
generate primitive accessor methods if the attribute is defined as an instance 
variable. http://goo.gl/vNFvZ This makes sense. Why would Core Data dynamically 
generate a primitive accessor using the storage of your custom subclass? 
Apple’s documentation illustrates this for a scalar attribute value.

As Jerry Krinock pointed out Core Data does undo/redo very reliably and I 
certainly need undo with this application. However customizing Core Data for 
this application has been a challenge to say the least. The documentation is 
extensive and accurate but you have to wade through the swamp and back to 
appreciate what the documentation is saying. You also have decide how far off 
the beaten path you want to travel and whether to do so is wise. You also need 
to occasionally consider if you are traveling in the right direction, which is 
how this thread started. Thanks to all for the insight and suggestions.

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: Detecting Managed Object Property Change From Undo Redo

2015-01-27 Thread Jerry Krinock

> On 2015 Jan 27, at 06:46, Keary Suska  wrote:
> 
> Better, however, to have a property declaration, which would also synthesize 
> an ivar in modern LLVMs (as of Xcode 5?).

You mean the property declaration would synthesize the ivar.  I didn’t try 
that.  I agree it would be better.

>> It still persists!
> 
> It will if you modeled it, which I didn't notice, but must be the case.

Yes, the data model has a ‘rating’ property.

> If we stop and think a moment, why would calling super ever work? This is 
> still Objective-C, and calling super is only valid when the class' superclass 
> implements the method. And I bet NSManagedObject doesn't…

Indeed, it crashed when I invoked it.

> Primitive methods … There is absolutely nothing magical about them, because 
> they need to be entirely un-magical to escape CD's notice.


> Therefore it is really hard to break anything unless you deliberately do so 
> (or deliberately ignore compiler warnings).

I don’t think it warned me about defining a primitive setter without a 
primitive getter, although it might have because I tried it in a project that 
is currently giving me 60 warnings due to major work in progress


___

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: Detecting Managed Object Property Change From Undo Redo

2015-01-27 Thread Jerry Krinock

> On 2015 Jan 27, at 01:24, Quincey Morris 
>  wrote:
> 
> I’m not sure that it’s “bad”, though it is nontypical, which is why there’s a 
> [nontypical] custom accessor. a Core Data property access has two general 
> steps … you can customize one or both of these steps.

OK, the documentation writer may have thought that customizing the 
representation or transformation between value and ivar, although untypical, 
would be a typical use case for Custom Primitive Accessor Methods, and 
therefore a good example, except that the writer neglected to write that.  
Instead, the writer merely showed some bare-bones code without explaining what 
it could do or why, which is why it made no sense to me.


___

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: Detecting Managed Object Property Change From Undo Redo

2015-01-27 Thread Keary Suska
> What in the world is that nonCompliantKVCivar?  I tried it in my project, on 
> the ‘rating’ property as in my YouTube video.
> 
> - (void)setPrimitiveRating:(NSNumber*)newRating {
>rating = newRating ;
> }
> 
> Does not compile.  The compiler never heard of ‘rating’.  Same result if I 
> change it to _rating, m_rating or nonCompliantKVCrating.  OK, so then I added 
> an ivar: _rating, and now of course
>   _rating = newRating ;
> compiles.

Remember that the compiler can't know anything about your model as all of that 
is specified at runtime. I wouldn't have expected CD to be smart enough to 
match up to a simply ivar declaration but it makes sense. Better, however, to 
have a property declaration, which would also synthesize an ivar in modern 
LLVMs (as of Xcode 5?).

> It still persists!

It will if you modeled it, which I didn't notice, but must be the case. It 
won't if you simply define an ivar or a property on your class and implement 
the relevant methods, however accurately.

> - (void)setPrimitiveRating:(NSNumber*)newRating {
>rating = newRating ;
>[super setPrimitiveRating:newRating] ;
> }
> 
> Result: Compiler warning that my superclass (eventually, NSManagedObject) did 
> not implement this method, a crash at runtime confirming that.

If we stop and think a moment, why would calling super ever work? This is still 
Objective-C, and calling super is only valid when the class' superclass 
implements the method. And I bet NSManagedObject doesn't...

> Conclusion: Primitive accessors are potentially useful but more study is 
> needed to understand how they work, and in particular how to override them 
> without breaking stuff.

Primitive methods are simply the methods for setting an objects values without 
being noticed--i.e. w/o causing KVO or changes notifications to be sent. I am 
sure you understand why. There is absolutely nothing magical about them, 
because they need to be entirely un-magical to escape CD's notice. Therefore it 
is really hard to break anything unless you deliberately do so (or deliberately 
ignore compiler warnings).

HTH,

Keary Suska
Esoteritech, Inc.
"Demystifying technology for your home or business"


___

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: Detecting Managed Object Property Change From Undo Redo

2015-01-27 Thread Quincey Morris
On Jan 26, 2015, at 23:32 , Jerry Krinock  wrote:
> 
> You seem to be saying that the only example given by Apple is a bad example, 
> because it is a a nontypical, special case.  I mean, most attributes in most 
> apps are objects, not scalars. 

I’m not sure that it’s “bad”, though it is nontypical, which is why there’s a 
[nontypical] custom accessor. A slightly different, but more plausible, case 
occurs when your property has (say) a NSPoint value. A point can be boxed in a 
NSValue object, but you might find it undesirable to keep boxing and unboxing, 
if the property is frequently accessed. To do that, you’d actually need to 
store the point unboxed, which means you need a real ivar.

What I think the documentation should say, but doesn’t lay out at all clearly, 
is that a Core Data property access has two general steps:

1. Representation of the value in backing storage.

2. Transformation of the backing storage value to vended @property value.

Ideally, and often, both steps are trivial — null, in fact. In that case, Core 
Data does all the work for you, and you do nothing except fake the compiler out 
by providing definitions of what Core Data will provide at run time. For 
example, if your Core Data model declares a string value, Core Data will 
normally represent it in its internal backing store as a NSString value, and 
clients using the property will see a NSString object.

But, you can customize one or both of these steps. For example, a scenario 
described in the documentation, you can customize step 2 to transform a NSColor 
object to/from a NSData object, which can be stored without a customized step 
1. This is complicated because Core Data supports multiple methods of 
transformation, including NSValueTransformer and custom accessors. And by the 
fact that KVO can independently bridge between scalar property values and boxed 
object values as necessary.

At the other end, you can customize step 1 by providing a non-object ivar, or 
by a collection of related ivars, or by a collection of primitive Core Data 
properties, or … . Depending on what you do, you may or may not need to 
customize step 2 as well.

Clearly, all this customization takes some coordination between steps 1 and 2, 
even if it’s just to know which of them needs to be customized in any 
particular case, and how. That where the documentation falls down — it gives 
recipes for a couple of scenarios, without helping you understand how to figure 
out other scenarios.

> It still persists!

Oh, well, it was a theory. 

___

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: Detecting Managed Object Property Change From Undo Redo

2015-01-26 Thread Jerry Krinock

> On 2015 Jan 26, at 22:14, Quincey Morris 
>  wrote:
> 
> On Jan 26, 2015, at 17:55 , Jerry Krinock  wrote:
>> 
>> What in the world is that nonCompliantKVCivar?  
> 
> It’s just an ivar that was defined separately from this particular code 
> fragment. It’s “non compliant” because Core Data doesn’t have a way of 
> backing a property with ‘short’ scalar storage.

I don’t think so, Quincey.  You seem to be saying that the only example given 
by Apple is a bad example, because it is a a nontypical, special case.  I mean, 
most attributes in most apps are objects, not scalars.  The ‘rating’ I used as 
an example is a NSNumber object.  But I really don’t think that matters to this 
discussion, so let’s move on…

> There’s sort of no point in doing exactly this, BTW …

> All that’s going on here is that Core Data doesn’t use ivars as backing 
> storage for properties …

> This explains, a primitive accessor. It’s a rare thing, an un-duck …

All very good explanations.

>> So this instance variable is somehow tied to the persistent store.  
> 
> It’s not, though. You must have done something wrong that made it work (!). I 
> have a theory about that, which I’ll get to in a moment.

I’m going to skip up to there now…

> My guess is that you provided an implementation of ‘setPrimitiveRating:’ (the 
> setter), but that you *didn’t* provide an implementation of ‘primitiveRating’ 
> (the getter).

Your guess was correct.  So I corrected that mistake and re-ran the experiment 
with both setter and getter,

- (void)setPrimitiveRating:(NSNumber*)newRating {
_rating = newRating ;
}
- (NSNumber*)primitiveRating {
return _rating ;
}

> you will then have to do extra work to get the value to persist, since the 
> ivar itself doesn’t”.


Nope.  It still persists!  Apparently, the persistent store is written by the 
public accessor, and/or there is some magical connection between the public and 
primitive.

But with my mistake corrected, the user interface now works again.  
Essentially, the app works just the same without those trivial primitive 
accessors and ivar, as with them.  So far, we’ve done no harm.

But the useful thing is that, as Richard Charles claimed, and I’ve now 
confirmed this, although the public accessors do not get invoked during Undo 
and Redo operations, the primitive accessors do.  So, provided that he 
implements both the primitive setter and getter, he can slip some code into the 
getter to post a notification of the value change.


___

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: Detecting Managed Object Property Change From Undo Redo

2015-01-26 Thread Jerry Krinock

On 2015 Jan 26, at 16:10, Richard Charles  wrote:

> It is not uncommon for this application to work with large data sets. I 
> tested using KVO on a managed object property and undo took 34 seconds. I 
> implemented custom accessors (public and primitive) containing custom change 
> code and undo took 3 seconds.

Very interesting result.

> I have not tested using NSObjectsChangedInManagingContextNotification to see 
> how long an undo would take but the thought looking through the notification 
> for specific properties in specific objects seems daunting. I saved out the 
> notification description for the change mentioned above and it was a 29 MB 
> text file. So using notifications from the managed object context for this 
> property change does not seem to be the way to go.

That’s probably true, but as you’ve found above, you never know about 
performance until you test it.

> It looks like using custom public and primitive accessors is the way go. Not 
> for everything, but where it is needed.

OK, although I’ve never used them, there is a section on "Custom Primitive 
Accessor Methods” in the Core Data Programming Guide, and it does not say not 
to.  The example they give is pretty confusing:

- (void)setPrimitiveInt16:(short)newInt16 {
nonCompliantKVCivar = newInt16;
}

What in the world is that nonCompliantKVCivar?  I tried it in my project, on 
the ‘rating’ property as in my YouTube video.

- (void)setPrimitiveRating:(NSNumber*)newRating {
rating = newRating ;
}

Does not compile.  The compiler never heard of ‘rating’.  Same result if I 
change it to _rating, m_rating or nonCompliantKVCrating.  OK, so then I added 
an ivar: _rating, and now of course
   _rating = newRating ;
compiles.  What was even more surprising is if I changed a ‘rating’ by clicking 
stars in the user interface, the user interface would not show the stars, until 
I closed and reopened the document; voila it had persisted!

So this instance variable is somehow tied to the persistent store.  I suppose 
this is explained by this documentation snippet:  "Typically there should be 
little reason to implement primitive accessor methods. They are, however, 
useful if you want custom methods to provide direct access to instance 
variables for persistent Core Data properties.”

The lack of action in the user interface is maybe explained by "they do not 
issue key-value access or observing notifications”.  OK, the user interface 
runs on Cocoa Bindings which runs on KVO.  But did my click not also run 
through the regular accessor, which does issue KVO?  I set a breakpoint and 
confirmed that setRating: was indeed the invoker of setPrimitiveRating:.

One more thing I tried: This is an override.  Should I not invoke super?

- (void)setPrimitiveRating:(NSNumber*)newRating {
rating = newRating ;
[super setPrimitiveRating:newRating] ;
}

Result: Compiler warning that my superclass (eventually, NSManagedObject) did 
not implement this method, a crash at runtime confirming that.

Conclusion: Primitive accessors are potentially useful but more study is needed 
to understand how they work, and in particular how to override them without 
breaking stuff.


___

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: Detecting Managed Object Property Change From Undo Redo

2015-01-26 Thread Richard Charles

> On Jan 26, 2015, at 12:10 PM, Jerry Krinock  wrote:
> 
> 
> On 2015 Jan 26, at 07:00, Richard Charles  wrote:
> 
>> Where do you post the notification from for a managed object property change?
> 
> Just to clarify: Your question refers to how I do it in my real apps, using 
> NSNotificationCenter, not how I did it in the YouTube video, which was 
> demonstating KVO.
> 
> Commonly, I use a custom setter, like this:
> 
> - (void)setRating:(NSNumber*)newValue {
>[self postWillSetNewValue:newValue
>   forKey:constKeyRating] ;
>[self willChangeValueForKey:constKeyRating] ;
>[self setPrimitiveRating:newValue] ;
>[self didChangeValueForKey:constKeyRating] ;
> }
> 
> wherein the -postWillSetNewValue:forKey: posts notifications.
> 
>> It doesn’t work in a managed object's custom public property accessor 
>> because the public property accessor is not called during undo redo.
> 
> Ah, I’d forgotten about that.  Indeed, the undo and redo tasks registered by 
> Core Data do not try and put things back in order using public accessors the 
> way I would (screw it up).  Instead, Core Data registers these annoyingly 
> opaque undo and redo tasks that, I presume, just change the whole object 
> graph to a previous (consistent) state in one fell swoop.  I think that’s why 
> Core Data does undo and redo so reliably.  But real apps often need to 
> observe all object changes, and so the resulting un-observability transfers 
> the complexity elsewhere. [1]
> 
> The way I’ve worked around that is to, as Mike Abdullah said, register for 
> NSObjectsChangedInManagingContextNotification.  I do it in a kind of “entity 
> manager” class that also does some fetching, etc.  But read the 
> NSObjectsChangedInManagingContextNotification documentation and understand 
> the edge cases in which this notification does not get sent.  Other patches 
> may be necessary.
> 
> So, going back to my YouTube video, I think you should take another look at 
> using KVO.  The fact that it "just works” with undo and redo is nice, and 
> with tricks like Kyle Sluder’s crafty -startObserving… and -stopObserving… 
> methods, the bookkeeping may be tractable.
> 
> 
> 1.  Google: “there are no solutions only tradeoffs”
> 

It is not uncommon for this application to work with large data sets. I tested 
using KVO on a managed object property and undo took 34 seconds. I implemented 
custom accessors (public and primitive) containing custom change code and undo 
took 3 seconds.

I have not tested using NSObjectsChangedInManagingContextNotification to see 
how long an undo would take but the thought looking through the notification 
for specific properties in specific objects seems daunting. I saved out the 
notification description for the change mentioned above and it was a 29 MB text 
file. So using notifications from the managed object context for this property 
change does not seem to be the way to go.

It looks like using custom public and primitive accessors is the way go. Not 
for everything, but where it is needed.

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: Detecting Managed Object Property Change From Undo Redo

2015-01-26 Thread Jerry Krinock

On 2015 Jan 26, at 07:00, Richard Charles  wrote:

> Where do you post the notification from for a managed object property change?

Just to clarify: Your question refers to how I do it in my real apps, using 
NSNotificationCenter, not how I did it in the YouTube video, which was 
demonstating KVO.

Commonly, I use a custom setter, like this:

- (void)setRating:(NSNumber*)newValue {
[self postWillSetNewValue:newValue
   forKey:constKeyRating] ;
[self willChangeValueForKey:constKeyRating] ;
[self setPrimitiveRating:newValue] ;
[self didChangeValueForKey:constKeyRating] ;
}

wherein the -postWillSetNewValue:forKey: posts notifications.

> It doesn’t work in a managed object's custom public property accessor because 
> the public property accessor is not called during undo redo.

Ah, I’d forgotten about that.  Indeed, the undo and redo tasks registered by 
Core Data do not try and put things back in order using public accessors the 
way I would (screw it up).  Instead, Core Data registers these annoyingly 
opaque undo and redo tasks that, I presume, just change the whole object graph 
to a previous (consistent) state in one fell swoop.  I think that’s why Core 
Data does undo and redo so reliably.  But real apps often need to observe all 
object changes, and so the resulting un-observability transfers the complexity 
elsewhere. [1]

The way I’ve worked around that is to, as Mike Abdullah said, register for 
NSObjectsChangedInManagingContextNotification.  I do it in a kind of “entity 
manager” class that also does some fetching, etc.  But read the 
NSObjectsChangedInManagingContextNotification documentation and understand the 
edge cases in which this notification does not get sent.  Other patches may be 
necessary.

So, going back to my YouTube video, I think you should take another look at 
using KVO.  The fact that it "just works” with undo and redo is nice, and with 
tricks like Kyle Sluder’s crafty -startObserving… and -stopObserving… methods, 
the bookkeeping may be tractable.


1.  Google: “there are no solutions only tradeoffs”


___

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: Detecting Managed Object Property Change From Undo Redo

2015-01-26 Thread Mike Abdullah

> On 26 Jan 2015, at 15:00, Richard Charles  wrote:
> 
> 
>> On Jan 25, 2015, at 4:16 PM, Jerry Krinock  wrote:
>> 
>> The reason I had to run that test is because I don’t use KVO for observing 
>> managed object properties.  Instead, I use NSNotificationCenter, which has 
>> these advantages…
> 
> Where do you post the notification from for a managed object property change? 
> It doesn’t work in a managed object's custom public property accessor because 
> the public property accessor is not called during undo redo. Only the 
> primitive set accessor is called.

I expect he’s observing NSManagedObjectContextObjectsDidChangeNotification.


___

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: Detecting Managed Object Property Change From Undo Redo

2015-01-26 Thread Richard Charles

> On Jan 25, 2015, at 4:16 PM, Jerry Krinock  wrote:
> 
> The reason I had to run that test is because I don’t use KVO for observing 
> managed object properties.  Instead, I use NSNotificationCenter, which has 
> these advantages…

Where do you post the notification from for a managed object property change? 
It doesn’t work in a managed object's custom public property accessor because 
the public property accessor is not called during undo redo. Only the primitive 
set accessor is called.

Great video by the way. Looks like an interesting application.

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: Detecting Managed Object Property Change From Undo Redo

2015-01-25 Thread Jerry Krinock

> On 2015 Jan 25, at 22:03, Kyle Sluder  wrote:
> 
> On Sun, Jan 25, 2015, at 05:16 PM, Jerry Krinock wrote:

>> • When an observer is being torn down you can remove all observers with
>> one line of code,
>> [NSNotificationCenter removeObserver:self].

> This is a dangerous API. If your superclass has registered for any
> observations, you will unregister before your superclass hears about it.

I see what you mean, that if the superclass needed for some reason to receive 
some notification at the bitter end of an object’s life, that line of code 
would break it.  I’m trying to imagine such a requirement.  Maybe to push 
changes to a data model in a view that was editing?  But we have various 
-endEditing methods for that.

On the other hand, I’ve seen many crashes occur from not removing observers 
early enough.  In general, as soon as it’s confirmed that an object is going 
away, the very first thing I do is to remove all of its observances.  It has 
worked for me, but from now on I’ll think about what you said.

> You can use the magic of C's sizeof keyword to avoid repeating yourself
> for each observed keypath:

And C arrays.  Very cool, Kyle.


___

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: Detecting Managed Object Property Change From Undo Redo

2015-01-25 Thread Kyle Sluder
On Sun, Jan 25, 2015, at 05:16 PM, Jerry Krinock wrote:
• Amount of code required is the same or less
> • Ability to coalesce and filter notifications per object or name
> • When an observer is being torn down you can remove all observers with
> one line of code,
>  [NSNotificationCenter removeObserver:self].

This is a dangerous API. If your superclass has registered for any
observations, you will unregister before your superclass hears about it.

> With KVO, if I recall correctly, you need to remember and remove each
> observance, arg.

You can use the magic of C's sizeof keyword to avoid repeating yourself
for each observed keypath:

static void *observationContext = &observationContext;
static NSString *observedKeypaths[] = {@"prop1", @"prop2"};

- (void)startObservingModelObject:(MyModelObject *)obj
{
  for (int i = 0; i < sizeof(observedKeypaths) /
  sizeof(*observedKeypaths); i++)
[obj addObserver:self forKeyPath:observedKeypaths[i] options:0
context:observationContext];
}

- (void)stopObservingModelObject:(MyModelObject *)obj
{
  for (int i = 0; i < sizeof(observedKeypaths) /
  sizeof(*observedKeypaths); i++)
[obj removeObserver:self forKeyPath:observedKeypaths[i]
context:observationContext];
}

--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

Re: Detecting Managed Object Property Change From Undo Redo

2015-01-25 Thread Jerry Krinock

On 2015 Jan 25, at 01:20, Mike Abdullah  wrote:

> You are mistaken. Core Data *does* fire KVO notifications during undo/redo.

Although I wasn’t aware of this, I just did a little experiment and found that 
Mike is correct…

http://youtu.be/PUHBAq-Me_4

On 25 Jan 2015, at 06:35, Richard Charles  wrote:

> The only solution seems to be to use custom primitive accessors that have 
> change notification.  What am I doing wrong?

I would not override the primitive accessors; instead I would override the 
regular accessors, or if you are using mogenerator, that has already been done 
for you.

The reason I had to run that test is because I don’t use KVO for observing 
managed object properties.  Instead, I use NSNotificationCenter, which has 
these advantages…

• Amount of code required is the same or less
• Ability to coalesce and filter notifications per object or name
• When an observer is being torn down you can remove all observers with one 
line of code,
 [NSNotificationCenter removeObserver:self].
With KVO, if I recall correctly, you need to remember and remove each 
observance, arg.

Just my two cents.  There are many ways to do this.


___

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: Detecting Managed Object Property Change From Undo Redo

2015-01-25 Thread Mike Abdullah

> On 25 Jan 2015, at 06:35, Richard Charles  wrote:
> 
> Core Data generated primitive accessors are used to get and set values from 
> and to the managed object's private internal store. Core Data generated 
> primitive accessors do not have change notification. If primitive accessors 
> are present, Core Data will use them during undo and redo.
> 
> A managed object may have resources that need to be updated when a property 
> changes. During undo and redo primitive accessors are used to change the 
> property but because primitive accessors do not have change notification 
> there is no way for the managed object to be notified that the property has 
> changed.
> 
> The only solution seems to be to use custom primitive accessors that have 
> change notification.
> 
> What am I doing wrong?

You are mistaken. Core Data *does* fire KVO notifications during undo/redo. Its 
internal implementation does something along these lines:

[object willChangeValueForKey:key];
[object setPrimitiveValue:previousValue forKey:key];
[object didChangeValueForKey:key];


___

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

Detecting Managed Object Property Change From Undo Redo

2015-01-24 Thread Richard Charles
Core Data generated primitive accessors are used to get and set values from and 
to the managed object's private internal store. Core Data generated primitive 
accessors do not have change notification. If primitive accessors are present, 
Core Data will use them during undo and redo.

A managed object may have resources that need to be updated when a property 
changes. During undo and redo primitive accessors are used to change the 
property but because primitive accessors do not have change notification there 
is no way for the managed object to be notified that the property has changed.

The only solution seems to be to use custom primitive accessors that have 
change notification.

What am I doing wrong?

Thanks,
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