- Retaining and Releasing
- Assigning to Instance Variables
- Automatic Reference Counting
- Returning Objects via Pointer Arguments
- Avoiding Retain Cycles
- Migrating to ARC
- Autorelease Pools
- Using Autoreleased Constructors
- Autoreleasing Objects in Accessors
- Supporting Automatic Garbage Collection
- Interoperating with C
- Understanding Object Destruction
- Using Weak References
- Allocating Scanned Memory
Assigning to Instance Variables
There are a few things that you have to be careful about when using reference counting in this way. Consider the following simple set method:
This looks sensible. You release the reference to the old value, then retain the new value and assign it. Most of the time, this will work, but in a few cases it won’t, and that can be confusing to debug.
What happens if the value of aString and string are the same? In this case, you are sending the same object a -release message then a -retain message. If some other code holds references to this object, it will still work, but if not then the first message will cause the object to be destroyed and the second will be sent to a dangling pointer.
A more correct implementation of this method would retain the new object first, as shown at the start of this section. Note that you should assign the result of the -retain message because some objects will return another object when you retain them. This is very rare, but it does happen on occasion.
Finally, this method is not thread-safe. If you want a thread-safe set method, you need to retain the new value, perform an atomic exchange operation on the result and the instance variable, and then release the old value. In general, however, it is almost impossible to reason about code that supports this kind of fine-grained concurrency, and the amount of cache churn it causes will offset any performance gains from parallelism, so it’s a terrible idea. If you really need it, it’s better to use declared properties to synthesize the accessor than try to write it yourself.