Xcode 4.5 and later auto-synthesizes properties, making an instance variable with the underscore prepended on the property name. But how does this work in an NSManagedObject? They want you to use KVC primitive methods in your custom setters. So what happens if you set an instance variable via the underscore ivar inside the NSManagedObject? Won't that screw things up since it would bypass the KVC methods? Or is it safely doing this behind the scenes?
If you access the underscore instance variable directly, you are bypassing the work that NSManagedObject does for you. You should use the get and set accessor methods that NSManagedObject auto-generates for your attributes.
Apple's documentation states
When you access or modify properties of a managed object, you should
use these [accessor] methods directly.
You can implement your own accessor methods if required, but in that case, you have to do additional work beyond changing the value of the instance variable:
You must ensure that you invoke the relevant access and change
notification methods (willAccessValueForKey:, didAccessValueForKey:,
willChangeValueForKey:, didChangeValueForKey:,
willChangeValueForKey:withSetMutation:usingObjects:, and
didChangeValueForKey:withSetMutation:usingObjects:).
This should illustrate that you can't get the correct behavior simply by modifying the instance variable directly.
Note that unlike ordinary properties, NSManagedObject properties are not synthesized at compile time (hence the use of #dynamic for the implementation). Since compile-time synthesis isn't used, there are no synthesized instance variables available for you to set.
Instead, instances of NSManagedObject have a private internal instance of something similar to an NSMutableDictionary to store their state. The dynamically generated property accessors are wrappers for calls to KVC-like methods that access the private storage.
Related
Sandy Metz says (POODR book, page 26):
Because it is possible to wrap every instance variable in a method and to therefore treat any variable as if it's just another object, the distinction between data and a regular object begins to disappear.
I am not sure if I understand what she is explaining. When we define the accessors, we are wrapping the instance variables (data) on a method but methods are not objects. So what does she mean when she says that we can treat variables as if they're just another object?
The primary difference between data and objects is behaviour. Objects can modify their internal state without changing their interfaces, while data are static structures.
When we wrap data access within a method, we get the same benefits of an object - the interface remains static to consumers even if the underlying data structure needs to change.
I am trying to get my head wrapped around "key-value coding".
Apple's docs say:
This document describes the NSKeyValueCoding informal protocol, which
defines a mechanism allowing applications to access the properties of
an object indirectly by name (or key), rather than directly through
invocation of an accessor method or as instance variables.
Few thing are confusing me
Accessor methods are automatically generated for properties, and provide several benefits like memory management, custom validations, etc. When we access a property without the accessor methods as the Apple doc says, does that mean we are losing the benefits of accessor methods?
If KVC is so good and it reduces code, why should I use accessor methods, or why are accessor methods still around?
I have never seen in any tutorial or books, or code on GitHub using KVC. Why is it not adopted that widely?
No, it just means that you aren't explicitly calling the accessor in your code. The accessor is called for you by the KVC implementation.
KVC doesn't necessarily reduce code, rather it allows a different way of interacting. It allows more runtime flexibility and it can allow the use of key paths. You shouldn't look at it as a full replacement, just as an alternative which is appropriate in some cases.
It is used widely, you need to look for calls to valueForKey:, setValue:forKey: (the methods of the protocol - there are many more than just these couple).
So far I have seen only CoreData using #dynamic property accessor definitions. What other ways are there for a property to get dynamic accessors in Cocoa object so that they can be marked as #dynamic?
You can generate an accessor at runtime by responding to +resolveInstanceMethod: (which is what Core Data does) or simulate it with -forwardInvocation:. I’ve seen this used in mock model objects which support arbitrary (object-valued) properties, although in that case properties were declared in unimplemented categories so no explicit #dynamic was used. (Actually, I’ve written a stupid hack that makes NSDictionary behave this way.)
I could imagine a similar approach being used for a proxy object.
By default, all declared properties are #dynamic, however you can declare them as #synthesize.
#dynamic means, that you will provide getter and setter implementation in your class, that may be linked to no any i-var.
You can declare a property dynamic yourself. This may be useful if, for example, the getter and setter methods are implemented by your superclass.
I got answer about Foundation magic for this question: What's the most *simple* way to implement a plain data object which conforms key-value-observing?
What's the magic? How it work internally? Because it's dangerous using framework which I can't understand its internal behavior, I want to know its behavior. Currently, I cannot understand how it work without any method definitions.
Apple's documentation describes how KVO is implemented internally.
The gist of it is that when you register an observer on an object, the framework dynamically creates a subclass of the object's original class, and adjusts the object to appear as an instance of this new dynamic class. You can see this if you inspect an object in the debugger after it has had an observer registered.
This new class intercepts messages to the object and inspects them for those matching certain patterns (such as the getters, setters, and collection access).
In a nutshell: Objective-C 2.0's #property declaration creates accessor methods for the named property, so there are method definitions. #property is just a shorthand way to define them which avoids a lot of repetitious boilerplate code.
When you observe a property, a private subclass is created which implements accessors that call the appropriate notification methods before and after changing the property value. A technique known as "isa swizzling" is then used to change the class of the observed object.
If I have a method with input that is used do I have to retain?
- (void) exampleMethod: (NSString *)input {
self.hey = [input retain];
}
What if I use input more than once?
Read the Memory Management Rules. If hey is a property with the retain or copy attributes set, then you do not need to invoke -retain on it (you can just do self.hey = input).
You don't need to retain a parameter that you only intend to use during the method. If you are going to keep a reference to it longer (as you seem to be in your example), then in most cases you should.
However, if you are using a property (which again you seem to be here), you should be managing the memory within the property setter itself, not calling retain explicitly when calling the setter.
In this case, the assignment to the .hey property a retain is implict in the accessor method.
Accessor Methods
If you want to continue using the string without using an accessor method, you may need to retain the string and the scope with which you need to have it available.