In my previous articles, you’ve probably seen properties used many times. In this article I wanted to write down (in one place) and explain the attributes that can be used on them. At least in this context, “attributes” refers to the modifiers to the property (usually strong and nonatomic in my previous articles). I have covered those two a little bit in a previous article, but I wanted to list them all here.
Valid Property Attributes
Properties are atomic by default, so if you don’t write nonatomic, it will be atomic (whether you write it or not). Atomic basically ensures that data is written or read atomically. So if thread A is still in the getter when thread B calls the setter, thread A will get a viable value. It is not necessarily thread-safe, but much safer than nonatomic. The problem with atomic though, is that it is quite slow compared to its opposite. Also, you must either implement both the setter and the getter, or neither. You cannot have a custom getter and a synthesized setter in an atomic property.
This makes no such guarantees about atomicity (which is quite a cool word) as nonatomic. If thread A is in the middle of a getter for a nonatomic NSString, and Thread B tries to set it to “Microwave”, and Thread C tries to set it to “Refrigerator”, you might get “Microgerator”, or it may just be completely unreadable and crash the program. You never know, so if you use nonatomic, you must implement your own thread safety and atomicity. You will more often use nonatomic properties though, because they are FAST when compared to atomic ones.
This is also a default attribute, and must be overridden if you want to change it. In ARC, its opposite is the “weak” attribute. I started post-ARC, so my first-hand knowledge is better with strong and weak, compared to the pre-ARC ones listed later. Strong is generally used by a class to establish ownership of an object. It increases the retain count (something ARC deals with for you), it basically keeps the object that is pointed to in memory until that class instance stops pointing to it. This is usually what you want, but there it can cause something called a “retain cycle.” The weak attribute helps solve this issue.
This gives a pointer to an object, but does not claim ownership, and does not increase the retain count. It basically keeps a valid pointer to an object as long as another class points to it strongly. If nothing else is trying to retain it, the weak pointer is automatically set to nil. An example where this would be useful is if you had two classes, one for a petOwner, and one for their pet. Lets say for some reason we want them to refer to each other, so you can request the pet of an owner, or an owner of a pet. If the pet’s petOwner property, and the petOwner’s pet property were both strong, the memory could never be released because they would both be telling ARC that they both need it. If we set the petOwner’s pet property to weak, then we avoid the retain cycle. If the pet object is destroyed, while the petOwner still has a reference to it, the petOwner’s pet property will be automatically set to nil.
This is a default attribute and it can be overridden by readonly. This basically tells the compiler to generate both a getter and a setter (or an accessor and mutator if you want to use fancy language).
This can override readwrite. It tells the compiler to only generate a getter for an object. One common thing to do with these two, is if you want a property visible to another class, but not able to be changed by an external class, set the property to readonly in your header file, and in your implementation file ( .m file), declare it as readwrite. That way your implementation has a getter and a setter, while external classes only get the getter.
This just gives a custom name for a getter. The default getter is just the name of the property. For instance for the UISwitch control in iOS, the property that says whether the switch is on is just named “on”. To make things a bit more readable, they set this attribute to “getter=isOn”. That way you can do something like this:
The getter= attribute is used purely for convenience or readability.
Similar to the getter=, it just gives a custom name to the setter. The default setter is just the capitalized property name with set as a prefix (so the default setter for “petOwner” is “setPetOwner”. This is again done purely for convenience or readability. I personally see this less often, but it is perfectly valid.
I have not used this one much, but here is what I have learned. It is similar to strong, but instead of increasing the retain count and claiming ownership of an object, it copies the value of the object that it is assigned to, and takes strong ownership of that copy. The object must conform to the NSCopying protocol to allow this to work.
A pre-ARC attribute. This is default behavior for primitive data types (like int, long, and float). It was used similar to “weak” for pre-ARC programs. It assumes the same ownership as “unsafe_unretained” mentioned below. It appears okay to use in an ARC project, but should be limited to properties for primitive types.
A pre-ARC attribute. This is the older version of strong. It claims ownership of the object and increases the retain count. You will have to manually release the object to decrease its retain count (which will release it from memory when the retain count goes to 0). You should not use this in an ARC project.
A pre-ARC attribute. This is similar to “weak”, but did not automatically set their value to nil if the referenced object was destroyed (as mentioned earlier). You should not use this in an ARC project.
Those are all of the possible attributes you can use on properties. Again, I started learning post-ARC, so my knowledge of assign, retain, and unsafe_unretained is somewhat lacking. I will try to fill these out more as I learn more about them, but these are good starting points. I know this is a rather long article, but I think this page will be useful if you ever need to know the difference between different property attributes.
I hope you found this article helpful. If you did, don’t hesitate to share this post on twitter or your social media of choice. The blog is still pretty new, and every share helps. Of course, if you have any questions, don’t hesitate to contact me on twitter @CodingExplorer, and I’ll see what I can do. Thanks!