Below two different paragraphs from Apple docs. In one paragraph, it says all class which inherits from NSObject to use KVO, is KVO compliant. In the second paragraph, it says not all classes are KVO compliant. Which are those classes which not KVO compliant? Is there any class which does not inherit NSObject? Whereas I know all inherit from NSObject.
It would ideal to give an example, to understand the difference between the two paragraphs.
To use KVO, first you must ensure that the observed object, the
Account, in this case, is KVO compliant. Typically, if your objects
inherit from NSObject and you create properties in the usual way, your
objects and their properties will automatically be KVO Compliant. It
is also possible to implement compliance manually. KVO Compliance
describes the difference between automatic and manual key-value
observing, and how to implement both.
and
Important: Not all classes are KVO-compliant for all properties. You
can ensure your own classes are KVO-compliant by following the steps
described in KVO Compliance. Typically properties in Apple-supplied
frameworks are only KVO-compliant if they are documented as such.
For a property of an object to be KVO-compliant, the object must inherit NSObject and the object must also either:
only update the property by using the property's setter method, or
manually notify when it modifies the property.
Since you don't have the source code for Apple's frameworks, you cannot in general know whether an object of an Apple-provided class obeys either of these requirements, except by checking the documentation. If the documentation says a property is KVO-compliant, you know it complies. Otherwise, you don't know if it complies so it is not safe to use KVO on the property.
It's important to understand that a property might sometimes be updated in a KVO-compliant way, and other times in a non-compliant way. So you can't just do a simple test to decide! Your test might show that the property is KVO-compliant for the way you set the property, but it cannot show that the property is always updated in a KVO-complaint way.
For example, every UIView owns a CALayer, and many of the UIView's properties, including its frame, its bounds, and its backgroundColor are actually properties of that CALayer. When you get or set the property on the view, the view's accessor method just sends the message on to the layer. But you can also set the layer's property directly. So if you say view.bounds = someRect, the view probably will notify KVO observers. But if you say view.layer.bounds = someRect, the view will not notify KVO observers. But after either of these statements, view.bounds will return someRect.
So, you can only rely on a property to be KVO-compliant if you are responsible for the implementation of that property, or if the property is documented to be KVO-compliant.
Key-Value Coding and Key-Value Observing are both dependent on naming conventions to identify which accessor methods correspond to which properties.
If you use declared properties (using the #property keyword) and you don't override the accessor method names, then the accessor methods will comply with the naming conventions and KVC and KVO will be able to identify the methods associated with a key. If you override the method names or use informal properties, then you are responsible for complying with the naming conventions. (One common case for this is using getter=is<Key> for a boolean property. It's an overridden getter name, but it still complies with the naming conventions.)
In addition to using accessor methods with conventional names, a class must also actually use the accessors to modify its own properties in order to take advantage of automatic change notification. The class should not directly modify its instance variables (outside of init methods or -dealloc) or, if it does, it needs to use manual change notification for that property.
What the first quote you cite is saying is that you get a lot of automatic behavior from NSObject, assuming you follow the naming conventions and modify your properties via their accessors rather than instance variables. That's what "create properties in the usual way" is getting at.
What the second quote is saying is that you can't assume that Apple's own classes do that. In some cases because of historical implementation details and in general for flexibility, they reserve the right to make their classes' properties non-compliant. You must not assume that the properties are KVO compliant unless they are specifically documented to be so.
Related
Im trying to understand the high level implementation of protocols without delegates in Apple frameworks. When a subClass conforms to and implements a protocol method, how is that method called? Lets consider the NSCoder protocol methods (encodeWithCoder: and initWithCoder:) for instance.
Without delegates, could you provide any uses cases for protocols (other than achieving polymorphism? I see that some methods could be abstracted away from base classes and grouped into an interfaces but without any implementation (as mixins for instance), what is the significant use?
First, protocol methods are not special in any way. They, like every other Objective-C method, gets called by a message sent to an object. There's nothing special about that part of things. Protocols are basically just a hint to the compiler, though you can query whether an object conforms to one at runtime and make decisions based on that.
You can verify this by implementing a protocol method (or the entire protocol) without declaring that fact in a classes' interface, and call the function on an instance of that object after casting it to be id<YourProtocol>, and it will work.
You can (and sometimes should) call NSCoding methods yourself -- you may decide that you want to persist objects to the disk, and that this is the best way to do it.
NSCoding is actually a great example of why protocols are still useful even though they do not provide any implementation -- the implementation of initWithCoder: and encodeWithCoder: will be different for every class that implements them -- there is no sense in providing an implementation.
Building on that, consider the datasource property of a UICollectionView; as there is no multiple inheritance in Objective-C, it would be undesirable for the datasource to be a class itself, as that would prevent you from using a UIViewController as the data source, and force you to make a whole new class for that express purpose.
Protocols can also be used to implement multiple inheritance in a type safe way without redeclaring the interface of the giver in the inheritor. If the entire interface of the class being inherited from is a protocol, then the inheritor can simply conform to that protocol as well.
Objective-C does provide mixins in the form of Categories, which can implement protocols on existing classes.
For a full throated defense of protocols (in Swift), see the Protocol-Oriented Programming WWWDC 2015 talk.
Taking the example of the NSCoding Protocol, the two required methods in the protocol, basically implement the steps an object should perform to encode itself to be archived. It also implements the initWithCoder to recreate the object from the archive.
Lets say you create a custom object, only your object knows which properties it needs to archive.
When you call a method to archive your custom object, the method call ultimately flow to your encodeWithCoder or initWithCoder to take action specific to your class.
***** Updated ****
Looking at this with an example :
Lets say our data structure looks like this
someArray = [String,CustomObject,aDictionary]
When we want to archive someArray, we call the archiveRootObject method on it. Now inorder for someArray to archive itself, it needs all its contained items to inturn archive themselves. The Array simply instructs the sub items to archiver themselves calling the encodeWithCoder method on them.
By adopting and conforming to the NSCoding protocol, you are just confirming to the root array that Yes, I know how to archive and unarchive myself.
Hope this helps.
How come properties have user settable attributes for storage and lifetime, but ivars don't. Especially considering the fact that a property is backed by an ivar.
Instance variables can have attributes, such as __strong, __weak, __unsafe_unretained, etc.
Also, as others have noted, properties are about behavior. They declare accessor methods and calling an accessor method is invoking behavior. Also the property is interface, while instance variables are implementation. As such, properties communicate the design contract to clients of the class. That's not necessary with instance variables, since clients should ideally be ignorant of implementation details.
Properties are not always backed by an ivar. Properties are just promises to implement accessors. If you don't implement the accessors yourself, then the system will automatically write some for you (called "synthesizing"), and will create an ivar as an implementation detail. The attributes you're describing are instructions to the compiler about how you want the synthesized accessors written.
Prior to ObjC 2, we wrote all our accessors by hand. Properties and synthesized accessors were added later to automatically implement patterns that had been long established at that point.
Because the effect of a #property is basically a superset of what you get by declaring an instance variable. With #property you're telling the compiler to create an instance variable along with accessor methods. The extra details tell it how those accessors should work. With an instance variable you're just declaring the ivar and leaving it at that.
I've read more than once that the Delegate Pattern used in Cocoa is an implementation of the Adaptern Pattern (http://en.wikipedia.org/wiki/Adapter_pattern).
They share the same intent, which is: let two objects with incompatible interfaces to work with each other.
The delegate object is the Adapter, because it adopts a protocol required by a client, the class that requires the protocol and has a weak reference to a delegate is the Client (so, this would be a class of the Cocoa framework).
My question is: who is the Adaptee? The delegate pattern doesn't wrap itself around any object, from what I've seen, who is the object that needs to be adapted?
Delegates are not really an example of the Adapter pattern. Protocols would be closer, but the best way to implement the Adapter pattern in Objective C is to create a new object that contains the object you want to adapt and uses it to serve a client.
Categories are another way of implementing the Adapter pattern, but they have some limitations. You can't override the implementation of existing methods in a category, and you can't add additional instance variables to a class with a category. However you can implement properties using associated objects and you can also add new instance methods.
You can also use multiple inheritance to implement the Adapter pattern in languages like C++ that offer it, but Objective-C does not support multiple inheritance.
A simple example of an Adapter using a category that I use in my projects is as follows:
Interface Builder (IB) includes a feature called "User Defined Runtime Attributes" that lets you set properties on your custom interface objects using Key Value Coding (KVC). It lets you specify a limited number of data types (ints, floats, bools, points, rects, UIColors, and a few others.)
You can use User Defined Runtime Attributes to set the border width and corner radius on a view's layer, and you SHOULD be able to use it to change the layer's border color or background color. However, layer colors are specified as CGColors, and UIViews use UIColors. Since IB only accepts UIColors in a User Defined Runtime Attribute, it doesn't work.
To fix this, I created a category of CALayer called CALayer+setUIColor. It has 2 methods, setBorderUIColor and setBackgroundUIColor. Those methods are very simple. They take UIColors as input, and simply convert the UIColor to a CGColor and set the layer's border color or background color.
You can see an early version of this category in my github project KeyframeViewAnimations.
I'd say that is a completely wrong view of the Cocoa delegate pattern.
The object needing a delegate is intentionally left incomplete. But instead of having an abstract class and adding the required functionality through subclassing, we add the required functionality by providing another object, the delegate.
Nowadays people will more and more switch from using delegate objects to providing the required functionality by passing one or more blocks instead.
I've found a solution in the official documentation, as I suspected there is no adaptee:
https://developer.apple.com/legacy/library/documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaDesignPatterns/CocoaDesignPatterns.html#//apple_ref/doc/uid/TP40002974-CH6-SW5
Delegation is not a strict implementation of the Decorator pattern.
The host (delegating) object does not wrap an instance of the class it
wants to extend; indeed, it’s the other way around, in that the
delegate is specializing the behavior of the delegating framework
class. There is no sharing of interface either, other than the
delegation methods declared by the framework class.
Delegation in Cocoa is also part of the Template Method pattern
(Template Method).
Source: https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaDesignPatterns/CocoaDesignPatterns.html#//apple_ref/doc/uid/TP40002974-CH6-SW19
The DELEGATE object is Adapter because:
It uses special protocol of special object and wrap it to itself special protocol.
Since Objective-C 2.0 we have properties, a nice syntax for getting and setting values for instance variables. Since Clang 3.1 all properties which are not dynamic, not readonly with an explicit getter or don't have a custom getter and setter are automatically synthesized to ivars. And since ARC we have weak/strong annotations for properties which are used by ARC to define the memory management logic of automatically synthesized properties.
The properties still can be synthesized manually e.g. for a readonly property backed by an ivar and returning a default value, for instance.
Sometimes, properties are also useful if they are not synthesized at all. I have found a few use cases when I use this sort of behavior:
A custom getter and setter which use a custom ivar for storing the actual value and which perform some additional actions.
A dynamic property, e.g. in subclasses of NSManagedObject.
A readonly property which simply passes through a property of an object stored in another property (e.g. a private one).
The Question: Does it makes sense to annotate these non-synthesized properties with weak/strong according to their actual usage or not? What is the best practice?
(https://twitter.com/kubanekl/status/427142577310408704)
I would say the answer is yes, even if only for documentation sake.
Even if you do not use any of the compiler and framework related default implementations, and implement everything by yourself, someone attempting to use these properties will be in much better position of understanding the API if he is able to get a hint on how the memory management would behave. A person does not really have to know how a setter or a getter is implemented internally, but he would might have to know, for example, if after calling a setter, the value was copied or retained or just assigned, and implement his side of things accordingly.
Yes, it does.
The property definition is a contract specification. Just because the compiler isn't fulfilling the contract doesn't mean you shouldn't respect it when manually implementing the accessor methods.
According to Ensuring KVC Compliance,
For properties that are an attribute or a to-one relationship, this requires that your class:
Implement a method named -<key>, -is<Key>, or have an instance variable <key> or _<key>.
What is the best way to add observers to "FAKE" properties like the following?
#property (nonatomic, readonly) BOOL shortlisted;
#pragma mark - Fake properties
- (BOOL)shortlisted
{
return [self.provider isJobShortlisted:self];
}
Dependent Keys
If you simply have one key which is dependent on another key of the same object, you can override +keyPathsForValuesAffectingValueForKey:. (See also this article for a common pitfall.)
The KVO documentation has information about keys dependent on other objects, but unfortunately it looks like this only has built-in support on OS X (not iOS).
Manual Notifcations
If you're implementing a completely custom property, the section on Manual Change Notification in the KVO docs has all the information you need. The key points are (with quotes from the docs):
A class that implements manual notification must override the NSObject implementation of automaticallyNotifiesObserversForKey:. ... For properties that perform manual notification, the subclass implementation of automaticallyNotifiesObserversForKey: should return NO.
To implement manual observer notification, you invoke
willChangeValueForKey: before changing the value, and didChangeValueForKey: after changing the value.
(If you change multiple properties, you can nest these calls.)
In the case of an ordered to-many relationship, you must specify not only the key that changed, but also the type of change and the indexes of the objects involved.
For this you use the methods willChange:valuesAtIndexes:forKey: and didChange:valuesAtIndexes:forKey:.