when to use "willChangeValueForKey" and "didChangeValueForKey"? - objective-c

I saw these lines in a demo project, but I couldn't understand why it did that.
[self willChangeValueForKey:#"names"];
[self didChangeValueForKey:#"names"];
It called didChangeValueForKey immediately after willChangeeValueForKey.
Does it make any sense?
Furthermore, when should be the right time to call this two methods?
Thanks a lot!! :)

This is, in fact, an anti-pattern. You should not call -willChangeValueForKey: followed by -didChangeValueForKey: without any intervening actual property change. In some cases, doing so can mask KVO problems elsewhere in your code and force observers to update their state related to the property in question. Ultimately, however, you (or the author of the example you cite) should fix the rest of the code so that this anti-pattern is unnecessary.
The correct usage of -will|didChangeValueForKey: is when you are modifying a property without using KVC-compliant accessors/setters such that the KVO mechanism would not notice the change. For a contrived example, consider modifying the backing instance variable for an attribute directly:
#interface Foo
{
int bar;
}
#end
#implementation Foo
- (void)someMethod
{
bar = 10;
}
#end
KVO observers that had registered for notification of changes in the bar property would not recieve notification of the change to bar in -someMethod. To make the KVO machinery work, you could modify -someMethod:
- (void)someMethod
{
[self willChangeValueForKey:#"bar"];
bar = 10;
[self didChangeValueForKey:#"bar"];
}
Of course, it would be better to use a #property declaration and to use KVC-compliant accessors/setters (either manually coded or #synthesized), but this is a contrived example.

KVO will operate correctly with custom setters for properties; this has always been the case for NSObject-derived classes. The runtime machinery looks for an invocation of the relevant setter method, and implicitly calls "willChangeValueForKey" prior to executing the setter, then implicitly calls "didChangeValueForKey" after the setter completes.
You can disable this automatic behavior if you wish to have more fine-grained control over KVO notifications. As mentioned above, readonly properties whose value you change by modifying the backing ivar, or whose values are derived by calculation, are places where you would use the manual notifications (although there is a mechanism, keyPathsAffectingValueFor, where you can tell the runtime that the value of a property is dependent on the change of another property, and it will send the change notification as appropriate.) To disable the automatic behavior on a per-property basis, you put in a class method + (BOOL) automaticallyNotifiesObserversOf and return NO.
I often disable automatic KVO notifications, because I have found that a KVO notification is generated when invoking a setter, even if the value of the property is being set to the same as its current value (e.g. no change). I wish to suppress the pointless notification for efficiency's sake:
+ (BOOL)automaticallyNotifiesObserversOfMyProperty
{
return NO;
}
- (void)setMyProperty:(NSInteger)myProperty
{
if(_myProperty != myProperty)
{
[self willChangeValueForKey:#"myProperty"];
_myProperty = myProperty;
[self didChangeValueForKey:#"myProperty"];
}
}
A good discussion can be found in the NSKeyValueObserving.h header, that you can navigate to by CMD+clicking on the method names "willChangeValueForKey" and "didChangeValueForKey" in XCode.

Those have to do with manually controlling key value observing. Normally the system takes care of it but these allow you some control. Look at this documentation to understand when and how to use them here.

Agree with Barry. I just meet the same problem. Here is a case of using those two methods.
I declared a readonly property. So I can't use the property's accessor to change the value.
#property (nonatomic, readonly) BOOL var;
When I want to change the "var", I need to call these two methods manually. Otherwise, observers won't get notified.
self willChangeValueForKey:#"var"];
var = YES;
[self didChangeValueForKey:#"var"];

If you want to do stuff just before the value gets changed, use willChangeValueForKey.
If you want to do stuff just after the value gets changed, use didChangeValueForKey.
Edit: ignore me, was reading too fast - Barry is right :-)

Be really careful when overriding didChangeValueForKey:. The best thing is not to do it at all. But if you do, make sure you call super, otherwise you will have a memory leak as demonstrated here: https://github.com/jfahrenkrug/KVOMemoryLeak

if you rewrite property getter methods, please use it.
#property (assign, nonatomic, getter=isLogined) BOOL logined;

Posting this in July 2013, and it no longer seems to be necessary to call will/didChangeValueForKey. It seems to be taken care of automatically, even if you have a custom setter.

Related

Objective-C use property and it's storage location. Difference?

What is the difference between property name and property storage location?
I must use only property name or mm what is the point to use first or the second?
Here is my example:
#implementation Car
#synthesize carSpeed = _carSpeed;
-(void) someMethod:(double)speed
{
self.carSpeed = speed; // this is the same am I right?
_carSpeed = speed;
}
#end
When directly accessing the instance variable (the storage location) there is no way other code can be notified of this change and do something about this. Using the property (using the dot syntax) is nothing more than a message send to the setter.
self.carSpeed = speed;
is exactly the same as
[self setCarSpeed: speed];
For once this enables automatic KVO to work, observers for this property will be notified that it changed.
Also since this is a regular message send the regular message dispatch happens. So you can override the setter in a subclass to change it’s behavior. Or you can change the implementation of the getter and setter to use some other kind of storage for the value instead of an instance variable without having to change any code that needs to change or read that property value.
Before we had ARC another important reason to use the accessors everywhere was that they are supposed to take care of memory management.
self.carSpeed = speed;
This uses setter method
Whereas,
_carSpeed = speed;
uses directly the ivar or property through the alias created.
Using . notation gives you the facility to access them from outside the class and setters and getters are in public zone.
Whereas, _carSpeed makes it local to the class. And more it is a old convention.
Synthesized property and variable with underscore prefix: what does this mean?

objective C underscore property vs self

I'm was playing around with the standard sample split view that gets created when you select a split view application in Xcode, and after adding a few fields i needed to add a few fields to display them in the detail view.
and something interesting happend
in the original sample, the master view sets a "detailItem" property in the detail view and the detail view displays it.
- (void)setDetailItem:(id) newDetailItem
{
if (_detailItem != newDetailItem) {
_detailItem = newDetailItem;
// Update the view.
[self configureView];
}
i understand what that does and all, so while i was playing around with it. i thought it would be the same if instead of _detailItem i used self.detailItem, since it's a property of the class.
however, when i used
self.detailItem != newDetailItem
i actually got stuck in a loop where this method is constantly called and i cant do anything else in the simulator.
my question is, whats the actual difference between the underscore variables(ivar?) and the properties?
i read some posts here it seems to be just some objective C convention, but it actually made some difference.
_property means you are directly accessing the property.
self.property means you are using accessors.
In your case, in the setter method you are calling it, creating a recursive call.
In the course of your experiment, you've set up an endless loop which is why the simulator goes non-responsive.
Calling self.detailItem within the scope of setDetailItem: calls setDetailItem: recursively since your class implements a custom setter method for the property detailItem.
I would refer you to the Apple documentation on declared properties for the scoop on properties, ivars, etc; but briefly, declared properties are a simplified way of providing accessor methods for your class. Rather than having to write your own accessor methods (as we had to do before Objective-C 2.0) they are now generated for you through the property syntax.
The properties are basically a way of the compiler to generate a setter and getter for a given instance variable.
So when you use something like:
id detailItem = self.detailItem;
what you are doing under the hood is:
id detailItem = [self detailItem];
Same for:
self.detailItem = otherDetailItem;
would be:
[self setDetailItem:otherDetailItem];
So when you write the setter yourself.. you get in an infinite loop since you access the method itself in itself.
You can freely make use of the 'self.' notation in your class, just not when you're overriding the setter or accessor because of the mechanism I described above.
Cases in a class where I use the . notation over simply accessing the ivar is when I change the value, you never know inside your class what needs to happen when you change the value. do you have something in terms of a status that should notify some delegate that a status changed? Usually this is not the case, however, just by using the . notation you are making sure that in the future you won't have to refactor some code if you did decide to do some magic in your setter method.
I'll make an example (without ARC enabled):
#property (nonatomic, retain) NSNumber* number;
If you don't synthesize it, you can access it this way:
self.number= [NSNumber numberWithBool: YES];
This case the number is retained.If instead you synthesize it and don't use the property:
#synthesize number;
Later in the file:
number=[NSNUmber numberWithBool: YES];
You haven't used the property, so the number is not retained.That makes a relevant difference between using accessors and synthesized properties.

Providing your own setter for a CoreData property / attribute

I have an entity with several properties, one of them called lastModificationDate. Whenever any of the object's properties is set, I'd like to update the lastModificationDate.
If I were not using Core Data, I would just provide my own setter for the properties and update lastModificationDate. However, I'm not sure if I should mess around with CoreData's properties.
What's the best way to do this?
Overriding the setters can easily be done, you have to make sure you fire the right notifications for everything else to work (including KVO).
- (void) setThing:(NSObject *)myThing {
self.lastUpdateDate = [NSDate date];
[self willChangeValueForKey:#"thing"];
[self setPrimitiveThing:myThing];
[self didChangeValueForKey:#"thing"];
}
This being said, if all you need to do is the code I showed (essentially setting the value and updating the last update date), you are much better off using Key-Value Observing and reacting to the notifications. It's easier and cleaner.
You shouldn't override property mutators (setters) if you're working with an NSManagedObject subclass because those implementations are provided at runtime (hence #dynamic instead of #synthesize). You could if you really wanted to, but it's messier and there's no reason to. Use Key Value Observing (KVO) instead. It'll let you know when a value is changed.
Apple's KVO documentation is great: https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/KeyValueObserving/KeyValueObserving.html#//apple_ref/doc/uid/10000177i

#property, setter and getter question?

NSString *statusValue;
NSString *currentValue;
#property(retain, nonatomic) NSString *statusValue;
#property(retain, nonatomic) NSString *currentValue;
#synthesize statusValue;
#sythnesize currentValue;
Given the above, if I am setting one variable to another should I be doing ...
[self setStatusValue: currentValue];
or should I use the property again and use ...
[self setStatusValue: [self currentValue]];
I suppose the latter (although maybe overkill) does tell the reader that we are using one of the objects instance variables and not some local variable.
just curious really, I was going with the bottom one, but just wanted to check before someone looked at my code and when "what the hell" :)
gary
Both work just fine. Which one you use may depend on the side-effects you wish. For example, by using [self currentValue], you may fire off willAccessValueForKey: and didAccessValueForKey: KVO notifications, but only if somebody's actually observing that property, and only if it's an NSManagedObject subclass. Usually there aren't any major side effects.
Personally, I'd probably use the latter example, just so that I don't have to worry about changing the name of an iVar in 30 places if I decide to change it (of course, the Refactor->Rename tool would be the right to use in that situation, but still).
I use the latter in the absence of a compelling reason not to. That way it works with overridden accessors, changed implementations, etc. without any changes. For example, maybe I decide to switch from storing the statusValue as a string and instead store a Status object with statusValue going through that. If I'm manually accessing the ivar all over the place, I have to change all of them. If instead I'm going through the class's public interface, I only have to change the one accessor method.
This works and is more expressive IMO:
self.statusValue = currentValue;

Difference between accessing property methods and class fields (Objective-C)

Assume that I have this piece of code:
#interface Foo : NSObject {
Bar *bar;
}
#property (retain, nonatomic) Bar *bar;
#end
When using this field/property, is there any difference between lines:
[self.bar doStuff];
and
[bar doStuff];
?
When doing assignment, property method will perform correct retaining, but what about the read access to the property, as described above? Is there any difference?
There is a big difference.
[self.bar doStuff] is equivalent to [[self bar] doStuff]
[bar doStuff] is equivalent to [self->bar doStuff]
The former uses the accessor method, the latter just accesses the instance variable bar directly.
If you use the #synthesize directive on your bar property, the compiler will generate two methods for you:
- (void)setBar:(Bar*)b;
- (Bar*)bar;
Also note, that the compiler generated setter method is retaining your Bar instance as you told it in the #property declaration.
Using the accessor self.bar is translated into a method call: [self bar]. The period syntax is just for looks. Accessing the member variable directly doesn't involve an extra function call, and is therefore slightly faster. It really only matters if you're accessing it within a loop, or in some process where that difference will add up. (On the iPhone) The setters created for properties also have some extra overhead for doing key value coding. A KVO notification is sent when you call "setBar:" or say "self.bar =" , so calling it over and over will result in a flood of notifications.
Jim is right, though - there's no functional difference between a nonatomic #property and a direct use of the variable in your code. Unless you're really concerned with the speed, using the property is probably your best bet.
A synthesized (or correctly hand-written) nonatomic accessor will be functionally equivalent to
- (Bar *)bar
{
return bar;
}
so there is no functional difference between your two examples.
However, outside of -dealloc or your initializers, consistently accessing the property via its accessor is a good idea.
If you assign value to your field with a convenient constructor of a Bar class, your Bar field will become a Zombie sooner than your Bar Property with Retain option, because reference count is not incremented by assigning to fields, and sometimes you run into "accessing deallocated objects" error.