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