#dynamic property accessors in Cocoa - cocoa

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.

Related

What is the purpose of protocols if all methods are optional?

I understand what purpose protocols serve (to have a type conform to a set list of methods or/and properties), but I don't understand what the purpose is of a protocol with all optional methods. One example would be UITextFieldDelegate.
If all methods are optional in a protocol, why would you conform to the protocol instead of just writing the methods from scratch in your class? I don't see what the benefit or purpose of conforming to the protocol is in this case.
Are the optional methods there just as suggestions of functionality that could be implemented?
Historically, for delegates and data sources in Cocoa, informal protocols were used. Informal protocol was implemented trough a category for NSObject class:
#interface NSObject (NSTableViewDelegate)
- (int)numberOfRowsInTableView:(NSTableView *)tableView;
// ...
#end
Later, optional methods in protocols were introduced. This change leads to better documenting of class responsibilities. If you see in code, that class conforms to NSTableViewDelegate, you suspect that somewhere exists a table view, that managed by instance of this class.
Also, this change leads to stronger checks in compile time. If programmer accidentally assign wrong object to delegate or dataSource properties, compiler will warn.
But your assumption is also correct. Optional methods are also suggestions for possible functionality.
By default, all methods in a protocol are required. Each method has to be marks as optional if the nor required for everything to function correctly.
If all methods are optional in a protocol, why would you conform to the protocol instead of just writing the functions from scratch in your class?
Conforming to a protocol allow your class to tell another object the methods it has without the other object needing to know about your class. This is really useful when using Delegation as it allows the delegate to decide what information they wish to receive/provide to another class.
For example,the UIScrollViewDelegate protocol only defines optional methods. Lets say we have a class Foo that we want to know when things change with a UIScrollView.
If we decided to throw that protocol away and implement the functions from scratch, how would we tell UIScrollView which methods we implement and which methods to call when certain event occur? There is no good way it could find out. When UIScrollView was built, it didn't know about Foo so it can't know what methods it implements. Also, Foo has no way of knowing what methods can be called on it by the UIScrollView.
However, when UIScrollView was built, it did know about UIScrollViewDelegate. So if Foo conforms the the UIScrollViewDelegate protocol, there is now a common definition that both Foo and UIScrollView can follow. So Foo can implement any methods it cares about, like scrollViewDidScroll: and the UIScrollView just needs to check if the delegate implemented the methods in UIScrollViewDelegate.
The protocol establishes a contract for the interface between one object and another. The fact that the methods are optional simply says that you don't have to implement that particular method, but you can if your app calls for it.
Generally, if you're conforming to a protocol for which all of the methods are optional, though, you're doing that for a reason, namely that you plan on implementing one or more of those methods. Just because all of the protocol's methods are optional doesn't mean you will not implement any of them, but rather simply that you can elect which are relevant in your particular situation.
For example, consider the UITextFieldDelegate protocol. You'd generally conform to that because you want to specify, for example, whether certain characters should be allowed to be inserted into the text field or what to do when the return key is pressed. Sometimes you only want to implement the former. Sometimes you only want to implement the latter. Sometimes you do both. But just because you choose to implement one or the other doesn't mean you necessarily want to do other one (but you can if you want). Frankly, though, if you really didn't want to implement any of the methods, you probably wouldn't even bother to specify the delegate of the text field, nor bother to specify that you're conforming to the protocol.
Bottom line, the protocol that consists solely of optional methods basically says "if you need it, this is the documented interface for the methods you may elect to implement". The protocol still is very useful to establish the possible interfaces, but doesn't force you to implement those methods you do not need.

How do automatically generated instance variables work in NSManagedObjects?

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.

How is Key-Value Observing implemented internally?

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.

Automatic Key-Value Observing in Cocoa

As I learn more about KVO and KVC, I have become curious -
How does NSObject provide automatic KVO when accessing setter methods?
If I create a new object with an accessor named setName,
how does an observer get notified when someon calls
[obj setName:#"Mystery"];
Thanks for any feedback
I always explain to people that "nothing is magic in Cocoa; it's just code." But KVO borders on magic. It's called isa-swizzling. Your class is transformed at runtime (the first time anyone observes you) into a dynamically generated sub-class that overloads all getters and setters. Calls to -class are wired to lie to you and return the old class, so you won't see the magic subclasses except in the debugger if you look directly at the isa pointer.
Noticing that KVO must be bizarre is a major step in Cocoa enlightenment. Congratulations.
Key-Value Observing Implementation Details

Should "to-many" relationships be modelled as properties?

After reading the Key-Value Coding Programming Guide, the Key-Value Observing Programming Guide and the Model Object Implementation Guide, as well as reading many StackOverflow entries on the topic and experimenting with various modelling scenarios, I feel like I have a good grasp on how to model my data.
I end up using declared properties for all my attributes and to-one relationships, backed by private ivars. For read-only attributes which need to be privately writeable, I use the readonly attribute in the .h interface declaration, then re-declare the property with the readwrite attribute in a class extension declared in the .m file. Inside the class methods, I always use the property accessors with the dot syntax and never access the private ivars directly.
There is however one aspect which still leaves me puzzled: how to properly model to-many relationships, especially when the collection is to be publicly immutable, but privately mutable (i.e. consumers of the model object cannot add or remove objects to the collection, but the collection's content is managed privately by the class).
I do understand how to implement the KVC accessor methods for to-many relationships (countOf<Key>, objectsIn<Key>AtIndex, etc.) and this is the route I've been following so far.
However, I've seen some sample code that uses declared properties to expose the relationships, do not implement the KVC accessor methods, yet are still Key-Value observable. For example:
#interface MyModel : NSObject
{
// Note that the ivar is a mutable array,
// while the property is declared as an immutable array.
#private NSMutableArray *transactions_;
}
#property (nonatomic, retain, readonly) NSArray transactions;
#end
--------------------
#implementation MyModel
#synthesize transactions = transactions_;
- (void)privateMethodThatManagesTransactions
{
[[self mutableArrayValueForKey:#"transactions"] addObject:t];
}
#end
If a consumer object adds itself as an observer of a MyModel instance for the "transactions" key path, it will be notified whenever transactions are added or removed from the transactions collection (as long as the mutations are done via the mutableArrayValueForKey: method).
To me, this seems like the cleanest way to expose to-many relationships as I don't need to hand-code the collection KVC accessors and it keeps the code clean.
However, it doesn't seem to be the way that is promoted by the Apple documentation, and I can't help but wonder if the fact that it works is only an unreliable side-effect.
So before commiting to one technique or the other in my real-life model classes for a project I'm beginning to work on, I'd like to get the opinion and advice of experienced Cocoa developers.
So the question is: if I use properties to model to-many relationships, do I still need to implement the KVC accessor/mutator methods?
Update
Even when I declare a to-many property as readonly, like in the example above, external code can still call mutableArrayValueForKey:#"transactions" on the model object and mutate the collection. This seems to indicate that using declared properties for to-many relationships isn't the way to go, but I still feel like I don't quite get it...
Yes.
There is however one aspect which still leaves me puzzled: how to properly model to-many relationships, especially when the collection is to be publicly immutable, but privately mutable ….
Easy: Declare the property as readonly in the header, then redeclare it as readwrite, copy in a class extension in the implementation file.
I do understand how to implement the KVC accessor methods for to-many relationships (countOf<Key>, objectsIn<Key>AtIndex, etc.) and this is the route I've been following so far.
There are mutative ones, too. With these, you don't need to use mutableArrayValueForKey:; instead, you can use the mutative accessors directly. You'll still get KVO notifications, because KVO wraps those methods the first time something adds itself as an observer for the property.
I have a list of the accessor selector formats, including the mutative accessors, on my blog.
Edit:
Even when I declare a to-many property as readonly, like in the example above, external code can still call mutableArrayValueForKey:#"transactions" on the model object and mutate the collection.
This is a good reason to make it a habit to use the mutative accessors and avoid mutableArrayValueForKey:. You won't send mutation messages from outside the class if you get a compiler warning (no such [public] method) any time you try it.
Despite the availability of mutableArrayValueForKey: and the risk that someone will use it, KVO-compliant properties are the way to go here.

Resources