How come ivars don't have attributes the way properties do - ios

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.

Related

Which all are class are not KVO compliant?

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.

Feature of ios instance variable

I recently mess up with property and ivar.
One very simple question but could not find answer.
Can I say instance var is strong and atomic ?
Thanks~
For instance variables containing object references, you can use the __weak or the __strong keyword. Default is __strong. If you also declare a property using the instance variable, this needs to agree with the property.
Instance variables cannot be atomic. Being atomic is not a property of an instance variable, it is a property of the code that is used to access it. Therefore properties can be atomic or nonatomic, but instance variables can't. Note that being atomic isn't particularly useful; that's discussed elsewhere.
Instance variables also cannot be readonly. If you have an instance variable, anyone who can access it can both read it and write it. On the other hand, instance variables can be #private, #protected or #public which properties cannot.
To give a broader answer:
A. ownership qualification (strong, weak, unsafe unretained)
As mentioned, (explicitly) declared ivars are strong by default as every other local var. You can change that behavior in the usual way with __weak or __unsafe_unretained.
If you have an (implicitly or explicitly) synthesized property and no (explicitly) declared ivar, the ivar is synthesized and inherits its ownership qualification from the property, which has an default strong ownership.
If you have an (explicitly) declared ivar that is bound to an (implicitly or explicitly) synthesized property, the ownership qualification of the property and the ivar shall be the same.
If a property is synthesized, then the associated instance variable is the instance variable which is named, possibly implicitly, by the #synthesize declaration. If the associated instance variable already exists, then its ownership qualification must equal the ownership of the property; otherwise, the instance variable is created with that ownership qualification.
http://clang.llvm.org/docs/AutomaticReferenceCounting.html#property-declarations
B. Atomicity
Atomicity has two effects:
The accessors are synchronized with an object level lock.
The lifetime of the return value exceeds the lifetime of the receiver.
The first subject is obviously related to control flow, not to ownership, so it has no effect on the ivar and you cannot qualify an ivar with atomicity.
The second subject means that you can imagine that the return value gets two additional messages in MRR:
return [[ivar retain] autorelease]
ARC respects that convention. However, using ARC the meaning of that is academical in usual code.
An instance variable is strong by default for objects, unless you use the __weak keyword, in which case it's weak.
It's never atomic unless you arrange to use a thread-locking mechanism when assigning it or accessing it.
Generally it's more convenient to use properties over instance variables.
Properties can be strong and atomic, and because strong and atomic are the default you can specify them like this:
#property id name;
Instance variables are strong by default but as they do not have accessors you need to do any locking yourself. One of the reasons it is better to use properties rather than access instance variables directly.

Weak/Strong Annotations for Non-Synthesized Properties in Objective-C

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.

Properties and their backing ivars

Hi imagine I have properties in the .h file:
#property (nonatomic) NSString * myText;
#property (nonatomic) SomeClass * someObj;
Now, in the class implementation.
Say, I didn't forget to use synthesize, and I called:
#synthesize myText, someObj;
Now say in code I forget to put self before the property name (and directly refer to the ivar):
myText = #"Hello";
someObj = [[SomeClass alloc] init];
My question is: is this a problem? What problems can it result in? Or it is no big deal?
ps. Say I am using ARC.
My question is: is this a problem?
This is called "direct ivar access". In some cases, it's not a problem, but a necessity. Initializers, dealloc, and accessors (setters/getters) are where you should be accessing self's ivars directly. In almost every other case, you would favor the accessor.
Directly accessing ivars of instances other than self should be avoided. Easy problem here is that you may read or write at an invalid address (undefined behavior), much like a C struct. When a messaged object is nil, the implementation of that message is not executed.
What problems can it result in?
Biggest two:
You won't get KVO notifications for these changes
And you are typically bypassing the implementation which provides the correct semantics (that can be justified). Semantics in this case may equate to memory management, copying, synchronization, or other consequences of a change of state. If, say, a setter is overridden, then you are bypassing any subclass override of that setter, which may leave the object in an inconsistent state.
See also: Why would you use an ivar?
For clarity, I recommend always using
self.propertyname
as opposed to
propertyname
as this removed any confusion between what variable belong to the class or have been declared locally above in the method.
To enforce this, try to avoid using #synthesize at all, which is only needed if you provide both custom getter and setter (but not one or the other)
The compiler automatically allows you to use _propertyname in the getter/setter (which is necessary to prevent recursive calls of the function)
You should not access the underlying instance variables by accident, only if you plan to do so.
Unexpected side effects may be that KVO doesn't work, overriding accessor methods are not called and the copyand atomic attributes have no effect.
You don't need to use #synthesize since Xcode 4.4, if you use default synthesis the compiler does an equivalent of
#synthesize myText = _myText;
so that
_myText = #"Hello";
self->_myText = #"Hello";
are equivalent and myText = #"Hello"; results in an "undefined identifier" compiler error.
If you use just #synthesize myText the compiler does (for backward compatibility reasons):
#synthesize myText = myText;
which is error prone.
Note that there are valid reasons to use the underlying instance variables instead of the accessor - but it's bad style to do this by accident.
For 30 years now, the recommended practice has been:
use getter/setter methods or the new . operator to read and write ivars.
only access ivars directly when you must.
pick ivar names to prevent accidentally using them, unless the ivar is one that will always be accessed directly (that is why the default behaviour and convention is to prefix ivars with an underscore).
You need to access ivars directly in a few situations:
Manual memory management requires it. You won't need this if ARC is enabled.
If you are going to read the variable variable millions of times in quick succession, and you can't assign it to a temporary variable for some reason.
When you're working with low level C API, it probably needs a pointer to the ivar, Apples libxml2 sample code accesses ivars directly for example.
When you are writing the getter or setter method yourself, instead of using the default #synthesize implementation. I personally do this all the time.
Aside from these situations (and a few others), do not access ivars directly. And prefix all ivars with an underscore, to make sure you don't accidentally access them and to prevent them appearing in xcode's autocomplete/intellisense while you code.
The two main reasons for the convention are:
Getter/setter methods and properties can be kept around when the underlaying memory structure of your class changes. If you rename an ivar, all code that reads the ivar will break, so best to have zero code or almost no code that accesses ivars directly.
Subclasses can override getters and setters. They cannot override ivars. Some people think subclasses shouldn't be allowed to override getters and setters - these people are wrong. Being able to override things is the entire point of creating a subclass.
Fundamental features like KVC and KVO can fall apart if you access ivars directly.
Of course, you can do whatever you want. But the convention has been around for decades now and it works. There is no reason not to follow it.
Contrary to what other answers seem to agree upon, I would recommend to always use direct ivar access unless you are very clear about what you are doing.
My reasoning is simple:
With ARC, it's not even more complicated to use direct property access, just assign a
value to the ivar and ARC takes care of the memory management.
(And this is my main point:) Property accessors may have side-effects.
This is not only true for property accessors you write, but may also be true for
subclasses of the class you are implementing.
Now these accessors defined in subclasses may very well rely on state that the subclass
sets up in it's initializer, which has not executed at this point, so you calling those
accessors might lead to anything from undefined state of your object to your application
throwing exceptions and crashing.
Now, not every class may be designed to be subclassed, but I think it's better to just use one style everywhere instead of being inconsistent depending on the class you are currently writing.
On a side note: I would also recommend to prefix the name of every ivar with an _, as the compiler will do automatically for your properties when you don't #synthesize them.

Do I need ARC keywords for properties that I don't synthesize?

I have a property that I do not synthesize, instead I create a getter and setter myself. Therefore, the ARC keywords (strong or weak) have no meaning, I assume, so I eliminate them. This works fine on Xcode 4.3, but when my coworker opens them on XCode 4.2 the compiler complains that there is no strong/weak keyword, so I instructed him to meaninglessly enter the keyword back in again. Which is correct (with or without keywords)?
To be clear: I have a property like this #property (nonatomic) NSString *foo and in the .m file I implement -(NSString *)foo and -(void)setFoo:(NSString *)foo and do NOT include #synthesize foo. Another relevant detail is that there is no corresponding iVar, instead the properties interact with a Core Data object. This will not compile in XCode 4.2 unless I add strong or weak to the keywords.
EDIT I thought of one more relevant thing, one of these properties is on a Protocol, I don't know if that makes a difference.
The declared attributes that you are referencing are optional. To quote the documentation:
Property Declaration and Implementation
The #property directive declares a property. An optional parenthesized
set of attributes provides additional details about the storage
semantics and other behaviors of the property - see “Property Declaration Attributes” for possible values.
Property Declaration Attributes
You can decorate a property with
attributes by using the form #property(attribute [, attribute2, ...]).
Like methods, properties are scoped to their enclosing interface
declaration. For property declarations that use a comma-delimited list
of variable names, the property attributes apply to all of the named
properties.
If you use the #synthesize directive to tell the compiler to create
the accessor methods (see “Property Implementation Directives”), the
code it generates matches the specification given by the keywords. If
you implement the accessor methods yourself, you should ensure that it
matches the specification (for example, if you specify copy you must
make sure that you do copy the input value in the setter method).
If you then use #dynamic instead of #synthesize it is telling the compiler that you will be writing your own methods and prevents it from complaining when it doesn't find suitable methods.
More information can be found here.
borrrden,
First, why do you care to elide your memory policy in your property statement? It announces to consumers of your class what the policy is. Don't you want them to know?
Second, the #synthesize is not a nop. It is the mechanism by which the language support KVO. While you may not be using that now, why would you preclude this use for the future.
Frankly, by not using a full description in #property nor using #synthesize, you are, IMO, engaging in premature optimization. Your current design doesn't save you message dispatches and forces you to manage, if necessary, the creation and typing of ivars. And you are losing features of the language.
Unless you have a good reason to get outside the bounds of the preferred Obj-C v2+ patterns, and you haven't listed those, then I would return to using the standard pattern. Then your problem just goes away.
Andrew

Resources