Where is the retain count stored for NSObjects in Objective C - objective-c

I am curious about how retain/release work internally. On the face, it seems like there's an integer related to each instance of an NSObject, which gets increased and decreased when you call -retain and -release, respectively.
But taking a look at NSObject, the only instance variable it has is the isa variable, for determining its class type.
So where are retain counts for individual objects stored? Not that I'm going to muck around with it, but just for my own edification.
Is it stored with the NSObject, but hidden away in some Objective C implementation detail? If so, that seems like a bad design to me. One should be able to create their own root class and handle their own retain/release counting in a similar fashion (not that it's a good idea--one would have to have a very good reason not to use NSObject).

The storage location for the retain count depends on both the runtime in use and the class implementation.
For Apple's Objective-C runtime, you can figure out a lot by digging into the source code of the Objective-C runtime.
For example, if you're using ARC (and I think even if you're not), the reference counts for most objects are stored in hash tables. Have a look at the _objc_rootRetain function in runtime/objc-arr.mm. I don't know exactly why they did this. Perhaps it's a way of keeping retain counts together for better cache behavior (which is important under ARC because ARC adjusts retain counts more often than non-ARC code usually does).
However, some classes override retain and related methods and store the retain count elsewhere. For example, when debugging a memory leak I discovered that CALayer does this. Instead of using the runtime's normal retain count mechanism, a CALayer stores its retain count in a private C++ implementation object. This is rather frustrating because it means the Instruments Allocations instrument doesn't log retains and releases of CALayer objects.

We do not know exactly how the data is stored, but we can rule out a few options:
Private Implementation Variables
We can rule this out, simply because when we iterate through the iVars of the NSObject class, we see only one: isa, as shown through this program:
id object = [NSObject new];
Class meta = object->isa;
printf("class name: %s\n", class_getName(meta));
unsigned count;
Ivar *ivars = class_copyIvarList(meta, &count);
for (int i = 0; i < count; i++) {
printf("iVar: %s\n", ivar_getName(ivars[i]));
}
free(ivars);
And note that even private implementation properties exist in the class metdata.
Private Properties
We can also rule this out, as even private properties are exposed in the classes metadata, as shown by the following example, there are no properties for the NSObject class:
id object = [NSObject new];
Class meta = object->isa;
printf("class name: %s\n", class_getName(meta));
objc_property_t *properties = class_copyPropertyList(meta, &count);
for (int i = 0; i < count; i++) {
printf("property: %s\n", property_getName(properties[i]));
}
Associated Objects
This one is very hard to rule out, as there are no direct ways to get a list of all the associated objects. However, since the concept of associated objects is very new, and reference counting has been around forever, I say that this is not very likely.
CoreFoundation struct-mangling
This is my best guess. When you create a NSObject, it is a struct behind the scenes. What is to say that the actual NSObject data representation is something like this:
typedef struct CFObject {
int retainCount;
id isa;
} *CFObjectRef;
Then, when an object is created:
id object_createInstance(...)
{
CFObjectRef object = malloc(sizeof(struct CFObject));
...
return (id) (object + sizeof(object->retainCount));
}
int object_retainCount(id self)
{
CFObjectRef asObject = (CFObjectRef) (self - sizeof(asObject->retainCount));
return asObject->retainCount;
}
I cannot verify this however, as there are many other ways this could be done (a map of integers to objects, for example).

It doesn't sound like it, but just in case... if you're thinking of using retain count directly, don't.
As for implementation details, sessions at WWDC 2011 mentioned that under ARC, most of the reference counting implementation has moved into the ObjC runtime. Source for that is available, so you might be able to find out for yourself how it works. For manual reference counting, much of the ObjC behaviors are replicated in CoreFoundation and libdispatch, which are also open source -- if you're looking to implement a similar scheme yourself, those might prove educational.
In general, this is an implementation detail for the same reason many things are: encapsulation is good policy, especially for framework providers. You don't want users of a framework depending on implementation details because then you can't change your implementation without breaking their code.

Don't know if this would be relevant, but I've stumbled upon the blog post about higher order messages implementation in the Objective-C. There author implements the HOM object as a root class (i.e. not inherited from NSObject) and the implementation looks like this:
#interface HigherOrderMessage {
Class isa;
NSUInteger retainCount;
//not relevant to this question part
}
Then the retain count managing methods are implemented like this:
- (id)retain {
__sync_add_and_fetch(&retainCount, 1);
return self;
}
- (id)autorelease {
[NSAutoreleasePool addObject:self];
return self;
}
- (void)release {
if (__sync_sub_and_fetch(&retainCount, 1) == 0) {
[methodSignatureForSelector release];
[forward release];
object_dispose(self);
}
}
This code actually works, so although we do not know how exactly the retainCount is implemented in the Cocoa classes, it is certain that it could be implemented in some similar way.

For addition insight, check out http://www.mikeash.com/pyblog/friday-qa-2011-09-16-lets-build-reference-counting.html, where Mike Ash explores an alternative implementation like the one Apple uses.

Related

How to replicate NSArray memory semantics in a subclass

Question
In my ARC project I have a class that manages objects, called LazyMutableArray. Some of the objects are actually nil, but users of my collection will never know about this; therefore I made it a subclass of NSMutableArray, and it tries to do "the same thing". In particular, objects are retained when added.
Now let's take a look at a memory behavior of other methods. It turns out that the NSArray destruction methods are documented by Apple to be an exception to this rule, in that they release, not autoreleased object.
There is some debate as to whether the combination of addObject: + objectAtIndex: + array destruction is documented by Apple to be never autoreleasing or simply happens to be in the examples I tested and in the example Apple includes.
How can I create in my subclass a method with exact same memory semantics?
Last update
After some thought, I've decided implementation based on NSMutableArray is more appropriate in this case compared to NSPointerArray. The new class, I should note, has the same retain/autorelease pair as the previous implementation.
Thanks to Rob Napier I see that no modification of my objectAtIndex: method would change this behavior, which answers my original question about this method.
On a practical level, several people said that any method can tackle an extra retain/autorelease pair for no reason; it's not reasonable to expect otherwise and not reasonable to try to find out which methods do this and which do not. It's been therefore a great learning opportunity for me on several levels.
Code (based on NSMutableArray) is available at GitHub: implementation, header, test (that's -testLazyMutableMemorySemantics).
Thank you all for participating.
Why I try to subclass NSMutableArray:
Subclassing foundation objects, I agree, is not always an appropriate solution. In tho case I have objects (in fact, OData resources), most of which have subobjects. The most natural class for an array of subobjects is obviously NSArray. Using a different class doesn't seem to make sense to me.
But for an OData collection this "array of sub objects", while, being an NSArray, must have a different implementation. Specifically, for a collection of 1000 elements, servers are encouraged to return collection in batches of (say)20, instead of all at once. If there is another pattern appropriate in this case, I'm all ears.
Some more detail in how I found this
I unit test the hell out of this collection, and values can be put into array, read from the array, and so forth. So far, so good. However, I realized that returning the object increases its retain count.
How do I see it? Suppose I insert two objects into lazy array lazy, one held weakly, one held strongly (*see the code *). Then retain count of weakSingleton is, as expected, 1. But now I read element:
XCTAssertEqual(weakSingleton, lazy[0], #"Correct element storage"); // line B
And in the debugger I see the retain count go up to 2. Of course, -retainCount may give me wrong information, so let's try to destroy the reference in array by
lazy[0] = nil; // yep, does the right thing
XCTAssertNil(weakSingleton, #"Dropped by lazy array"); // line C <-- FAIL
indeed, we see that weakSingleton is not released.
By now you probably guess that it's not just a retain, it's an autoreleased retain — putting an #autorelease around line B releases the weakSingleton. The exact source of this pair is not obvious, but seems to come from NSPointerArray -addPointer: (and unfortunately not from ARC's [[object retain] autorelease]). However, I don't want to return an autoreleased object and make method semantics different from its superclass!
After all, the method I'm overriding, NSMutableArray -objectAtIndex:`, doesn't do that; the object it returns will dealloc immediately if an array is released, as noted in the Apple's example. That's what I want: modify the method around line A so that the object it returns does not have an extra retain/autorelease pair. I'm not sure the compiler should even let me do it :)
Note 1 I could turn off ARC for a single file, but this would be my first non-ARC Objective-C code. And in any case the behavior may not some from ARC.
Note 2 What the fuss? Well, in this case I could change my unit tests, but still, the fact is that by adding or deleting line B, I'm changing the result of unit test at line C.
In other words, the described behavior of my method [LazyMutableArray -objectAtIndex] is essentially that by reading an object at index 0, I'm actually changing the retain count of this object, which means I could encounter unexpected bugs.
Note 3 Of course, if nothing is to be done about this, I'll document this behavior and move on; perhaps, this indeed should be considered an implementation detail, not to be included into tests.
Relevant methods from implementation
#implementation LazyMutableArray {
NSPointerArray *_objects;
// Created lazily, only on -setCount:, insert/add object.
}
- (id)objectAtIndex:(NSUInteger)index {
#synchronized(self) {
if (index >= self.count) {
return nil;
}
__weak id object = [_objects pointerAtIndex:index];
if (object) {
return object;
}
}
// otherwise do something else to compute a return value
// but this branch is never called in this test
[self.delegate array:self missingObjectAtIndex:index];
#synchronized(self) {
if (index >= self.count) {
return nil;
}
__weak id object = [_objects pointerAtIndex:index];
if (object) {
return object;
}
}
#throw([NSException exceptionWithName:NSObjectNotAvailableException
reason:#"Delegate was not able to provide a non-nil element to a lazy array"
userInfo:nil]);
}
- (void)createObjects {
if (!_objects) {
_objects = [NSPointerArray strongObjectsPointerArray];
}
}
- (void)addObject:(id)anObject {
[self createObjects];
[_objects addPointer:(__bridge void*)anObject];
}
The complete test code:
// Insert two objects into lazy array, one held weakly, one held strongly.
NSMutableArray * lazy = [LazyMutableArray new];
id singleton = [NSMutableArray new];
[lazy addObject:singleton];
__weak id weakSingleton = singleton;
singleton = [NSMutableDictionary new];
[lazy addObject:singleton];
XCTAssertNotNil(weakSingleton, #"Held by lazy array");
XCTAssertTrue(lazy.count == 2, #"Cleaning and adding objects");
// #autoreleasepool {
XCTAssertEqual(weakSingleton, lazy[0], #"Correct element storage");
XCTAssertEqual(singleton, lazy[1], #"Correct element storage");
// }
lazy = nil;
XCTAssertNotNil(singleton, #"Not dropped by lazy array");
XCTAssertNil(weakSingleton, #"Dropped by lazy array");
The last line fails, but it succeeds if I change first line to lazy = [NSMutableArray new] or if I uncomment #autoreleasepool.
First, I would not make this subclass. This is exactly what NSPointerArray is for. Wrapping that into an NSArray obscures important details that this approach can break. For example, what is the correct behavior for [NSArray arrayWithArray:lazyMutableArray] if lazyMutableArray includes NULLs? Algorithms that assume that NSArray can never include NULL need to be wary of the fact that this one can. It's true that you can get similar issues treating a non-retaining CFArray as an NSArray; I speak from experience that this is exactly why this kind of subclass can be very dangerous (and why I stopped doing that years ago). Don't create a subclass that cannot be used in every case that its superclass can be used (LSP).
If you have a collection with new semantics, I would subclass it from NSObject, and have it conform to <NSFastEnumeration>. See how NSPointerArray is not a subclass of NSArray. This was not an accident. Faced with the same problem, note the direction Apple chose.
By now you probably guess that it's not just a retain, it's an autoreleased retain — putting an #autorelease around line B releases the weakSingleton. This seems to be because line A under ARC translates to [[object retain] autorelease]. However, I don't want to return an autoreleased object and make caller remember this!
The caller should never assume anything else. The caller is never free to assume that a method does not add balanced autoreleases. If a caller wants the autorelease pool to drain, that is their responsibility.
All that said, there is some benefit to avoiding an extra autorelease if it's not required, and it's an interesting learning opportunity.
I would start by reducing this code to the simplest form, without your subclass at all. Just explore how NSPointerArray works:
__weak id weakobject;
#autoreleasepool
{
NSPointerArray *parray = [NSPointerArray strongObjectsPointerArray];
{
id object = [NSObject new];
[parray addPointer:(__bridge void*)object];
weakobject = object;
}
parray = nil;
}
NSAssert(!weakobject, #"weakobject still exists");
My structure here (such as the extra nesting block) is designed to try to avoid accidentally creating strong references I don't mean to make.
In my experiments, this fails without the autoreleasepool and succeeds with it. That indicates that the extra retain/autorelease is being added around or by the call to addPointer:, not by ARC modifying your interface.
If you're not using this implementation for addObject:, I'd be interested in digging deeper. It is an interesting question, even if I don't believe you should be subclassing this way.
I'm going to elaborate on why I said this "looks a lot like a homework assignment." This will likely earn me many down votes, but it will also server as a good learning case for others who later find this question.
Subclassing NSMutableArray not a goal of a program. It is a means to achieve something else. If I were to venture a guess, I expect you were trying to create an array that lazily creates the object when they are accessed. There are better ways to do this without dealing with memory management yourself.
Here's an example of how I would implement a lazy loading array.
#interface LazyMutableArray : NSMutableArray
- (id)initWithCreator:(id(^)(int))creator;
#end
#interface LazyMutableArray ( )
#property (nonatomic, copy) id (^creator)(int);
#property (nonatomic, assign) NSUInteger highestSet;
#end
#implementation LazyMutableArray
- (id)initWithCreator:(id(^)(int))creator
{
self = [super init];
if (self) {
self.highestSet = NSNotFound;
self.creator = creator;
}
return self;
}
- (id)objectAtIndex:(NSUInteger)index
{
id obj = nil;
if ((index < self.highestSet) && (self.highestSet != NSNotFound)) {
obj = [super objectAtIndex:index];
if ([obj isKindOfClass:[NSNull class]]) {
obj = self.creator(index);
[super replaceObjectAtIndex:index withObject:obj];
}
} else {
if (self.highestSet == NSNotFound) {
self.highestSet = 0;
}
while (self.highestSet < index) {
[super add:[NSNull null]];
self.highestSet += 1;
}
obj = self.creator(index);
[super add:obj];
self.highestSet += 1;
}
return obj;
}
Fair Warning: I'm not compiling or syntax checking any of this code. It probably has a few bugs in it, but it should generally work. Additionally, this implementation is missing an implementation of add:, count, removeObjectAtIndex:, insertObject:atIndex:, and possibly replaceObjectAtIndex:withObject:. What I show here is just to get you started.

Using objc_msgSendSuper to invoke a class method

I was going through and replacing #synthesized(self) locks w/ this method
void _ThreadsafeInit(Class theClassToInit, void *volatile *theVariableItLivesIn, void(^InitBlock)(void))
{
//this is what super does :X
struct objc_super mySuper = {
.receiver = (id)theClassToInit,
.super_class = class_getSuperclass(theClassToInit)
};
id (*objc_superAllocTyped)(struct objc_super *, SEL, NSZone *) = (void *)&objc_msgSendSuper;
// id (*objc_superAllocTyped)(id objc_super, SEL, NSZone *) = (void *)&objc_msgSend;
do {
id temp = [(*objc_superAllocTyped)(&mySuper /*theClassToInit*/, #selector(allocWithZone:), NULL) init];//get superclass in case alloc is blocked in this class;
if(OSAtomicCompareAndSwapPtrBarrier(0x0, temp, theVariableItLivesIn)) { //atomic operation forces synchronization
if( InitBlock != NULL ) {
InitBlock(); //only the thread that succesfully set sharedInstance pointer gets here
}
break;
}
else
{
[temp release]; //any thread that fails to set sharedInstance needs to clean up after itself
}
} while (*theVariableItLivesIn == NULL);
}
which while a bit more verbose exhibits significantly better performance in non-contested cases
along with this little macro (excuse poor formatting, it's very simple). To allow the block to be declared after the initial nil check, looks to help LLVM keep the "already initialized" path extremely fast. That's the only one I care about.
#define ThreadsafeFastInit(theClassToInit, theVariableToStoreItIn, aVoidBlockToRunAfterInit) if( theVariableToStoreItIn == nil) { _ThreadsafeInitWithBlock(theClassToInit, (void *)&theVariableToStoreItIn, aVoidBlockToRunAfterInit); }
So initially implemented it using the commented out sections for objc_superAllocTyped (actually first using [theClassToInit allocWithZone:NULL], which was definitely the best approach :) ), which worked great until I realized that most of the singletons in the project had overridden allocWithZone to return the singleton method... infinite loop. So I figured using objc_msgSendSuper should sort it out quickly, but I get this error.
[51431:17c03] +[DataUtils allocWithZone:]: unrecognized selector sent to class 0x4f9584
The error doesn't seem to be related to the actual problem, as...
(lldb) po 0x4f9584
$1 = 5215620 DataUtils
(lldb) print (BOOL)[$1 respondsToSelector:#selector(allocWithZone:)]
(BOOL) $2 = YES
So I'm definitely missing something... I compared to assembly generated by a [super allocWithZone:NULL] method in an empty class... almost identical except for the functions called have different names (maybe just using different symbols, no idea, can't read it that well).
Any ideas? I can use class_getClassMethod on the superclass and call the IMP directly, but I'm trying to be reasonable in my abuse of the runtime :)
Alright, this wasn't actually that tricky once I recalled that the meta class contains all of the method information for a Class instance obtained via -[self class] or +[self] -> thanks http://www.cocoawithlove.com/2010/01/what-is-meta-class-in-objective-c.html
This error occurred because I was asking the runtime to look up the method in NSObject's set of instance methods, which obviously doesn't contain allocWithZone: . The mistake in the error log presumably originated because the receiver was a metaclass instance, and Apple has their interns implement error logs.
so while with a normal instance method call via objc_msgSendSuper, you would pass a metaclass instance as objc_super.super_class, to invoke a class method, the metaclass itself is needed (everything is one level up).
Example, and a diagram that helped me understand this - (http://www.sealiesoftware.com/blog/archive/2009/04/14/objc_explain_Classes_and_metaclasses.html)
struct objc_super mySuper;
mySuper.receiver = theClassToInit; //this is our receiver, no doubt about it
//either grab the super class and get its metaclass
mySuper.super_class = object_getClass( class_getSuperclass( theClassToInit ) );
//or grab the metaclass, and get its super class, this is the exact same object
mySuper.super_class = class_getSuperclass( object_getClass( theClassToInit ) );
Then the message can be resolved correctly. Makes perfect sense now that I started paying attention :P
Anyways, now that I found my mistake I feel like I've leveled up my Objc runtime understanding. I was also able to fix an architectural mistake made two years ago by someone I never met without having to modifying and re-test dozens of classes across 3 projects and 2 static libraries (God I love Objective-C). Replacing the #synchronized construct with a simple function call also halved the compiled code size of those methods. As a bonus, all our singleton accessors are now (more) threadsafe, because the performance cost for doing so is now negligible. Methods which naively re-fetched the singleton object multiple times (or in loops) have seen a huge speedup now that they don't have to acquire and release a mutex multiple times per invocation. All in all I'm very happy it all worked as I'd hoped.
I made a "normal" Objective-C method for this on a category of NSObject, which will work for both instance and Class objects to allow you to invoke a superclass's implementation of a message externally. Warning: This is only for fun, or unit tests, or swizzled methods, or maybe a really cool game.
#implementation NSObject (Convenience)
-(id)performSelector:(SEL)selector asClass:(Class)class
{
struct objc_super mySuper = {
.receiver = self,
.super_class = class_isMetaClass(object_getClass(self)) //check if we are an instance or Class
? object_getClass(class) //if we are a Class, we need to send our metaclass (our Class's Class)
: class //if we are an instance, we need to send our Class (which we already have)
};
id (*objc_superAllocTyped)(struct objc_super *, SEL) = (void *)&objc_msgSendSuper; //cast our pointer so the compiler can sort out the ABI
return (*objc_superAllocTyped)(&mySuper, selector);
}
so
[self performSelector:#selector(dealloc) asClass:[self superclass]];
would be equivalent to
[super dealloc];
Carry on runtime explorers! Don't let the naysayers drag you into their land of handwaving and black magik boxes, it's hard to make uncompromisingly awesome programs there*.
*Please enjoy the Objective-C runtime responsibly. Consult with your QA team for any bugs lasting more than four hours.

Objective-C pattern for class instance variables?

What would be a nice pattern in Objective-C for class variables that can be "overridden" by subclasses?
Regular Class variables are usually simulated in Objective-C using a file-local static variables together with exposed accessors defined as Class methods.
However, this, as any Class variables, means the value is shared between the class and all its subclasses. Sometimes, it's interesting for the subclass to change the value for itself only. This is typically the case when Class variables are used for configuration.
Here is an example: in some iOS App, I have many objects of a given common abstract superclass (Annotation) that come in a number of concrete variations (subclasses). All annotations are represented graphically with a label, and the label color must reflect the specific kind (subclass) of its annotation. So all Foo annotations must have a green label, and all Bar annotations must have a blue label. Storing the label color in each instance would be wasteful (and in reality, perhaps impossible as I have many objects, and actual configuration data - common to each instance - is far larger than a single color).
At runtime, the user could decide that all Foo annotations now will have a red label. And so on.
Since in Objective-C, Classes are actual objects, this calls for storing the Foo label color in the Foo class object. But is that even possible? What would be a good pattern for this kind of things? Of course, it's possible to define some sort of global dictionary mapping the class to its configuration value, but that would be kind of ugly.
Of course, it's possible to define some sort of global dictionary mapping the class to its configuration value, but that would be kind of ugly.
Why do you think this would be ugly? It is a very simple approach since you can use [self className] as the key in the dictionary. It is also easy to make it persistent since you can simply store the dictionary in NSUserDefaults (as long as it contains only property-list objects). You could also have each class default to its superclass's values by calling the superclass method until you find a class with a value.
+ (id)classConfigurationForKey:(NSString *)key {
if(_configurationDict == nil) [self loadConfigurations]; // Gets stored values
Class c = [self class];
id value = nil;
while(value == nil) {
NSDictionary *classConfig = [_configurationDict objectForKey:[c className]];
if(classConfig) {
value = [classConfig objectForKey:key];
}
c = [c superclass];
}
return value;
}
+ (void)setClassConfiguration:(id)value forKey:(NSString *)key {
if(_configurationDict == nil) [self loadConfigurations]; // Gets stored values
NSMutableDictionary *classConfig = [_configurationDict objectForKey:[self className]];
if(classConfig == nil) {
classConfig = [NSMutableDictionary dictionary];
[_configurationDict setObject:classConfig forKey:[self className]];
}
[classConfig setObject:value forKey:key];
}
This implementation provides no checking to make sure you don't go over the top superclass, so you will need to ensure that there is a value for that class to avoid an infinite loop.
If you want to store objects which can't be stored in a property list, you can use a method to convert back and forth when you access the dictionary. Here is an example for accessing the labelColor property, which is a UIColor object.
+ (UIColor *)classLabelColor {
NSData *data = [self classConfigurationForKey:#"labelColor"];
return [NSKeyedUnarchiver unarchiveObjectWithData:data];
}
+ (void)setClassLabelColor:(UIColor *)color {
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:color];
[self setClassConfiguration:data forKey:#"labelColor"];
}
my answer here may help:
What is the recommended method of styling an iOS app?
in that case, your annotation just holds a reference to a style (e.g. you need only one per style), and the size of a pointer for an entire style is not bad. either way, that post may give you some ideas.
Update
Jean-Denis Muys: That addresses the sample use case of my question, but not my question itself (a pattern to simulate class instance variables).
you're right, i didn't know how closely your example modeled your problem and i considered commenting on that.
for a more general and reusable solution, i'd probably just write a threadsafe global dictionary if your global data is nontrivial (as you mentioned in your OP). you could either populate it in +initialize or lazily by introducing a class method. then you could add a few categories to NSObject to access and mutate the static data -- do this for syntactical ease.
i suppose the good thing about that approach is that you can reuse it in any program (even though it may appear ugly or complex to write). if that's too much locking, then you may want to divide dictionaries by prefixes or create a simple thread safe dictionary which your class holds a reference to -- you can then synthesize an instance variable via the objc runtime to store it and declare an instance method to access it. the class method would still have to use the global data interface directly.

Why shouldn't I use the getter to release a property in objective-c?

I was told by a fellow StackOverflow user that I should not use the getter method when releasing a property:
#property(nonatmic, retain) Type* variable;
#synthesize variable;
// wrong
[self.variable release];
// right
[variable release];
He did not explain in detail why. They appear the same to me. My iOS book said the getter on a property will look like this:
- (id)variable {
return variable;
}
So doesn't this mean [self variable], self.variable, and variable are all the same?
For a retained property with no custom accessor, you can release the object by:
self.variable = nil;
This has the effect of setting the ivar (which may not be called 'variable' if you have only declared properties) to nil and releasing the previous value.
As others have pointed out, either directly releasing the ivar (if available) or using the method above is OK - what you must not do is call release on the variable returned from a getter.
You can optionally write custom getter behavior, which may result in completely different behavior. So, you cannot always assume that [variable release] has the same results as [self.variable release].
As well, you can write custom properties without an exclusive ivar backing them... it can get messy fast if you start releasing objects from references returned by getters!
There may be additional reasons that I'm unaware of...
A typical getter will look more like this:
- (id)variable {
return [[variable retain] autorelease];
}
So if you use [self.variable release] you have an additional retain and autorelease that you don't really need when you just want to release the object and that cause the object to be released later than necessary (when the autorelease pool is drained).
Typically, you would either use self.variable = nil which has the benefit that it also sets the variable to nil (avoiding crashes due to dangling pointers), or [variable release] which is the fastest and may be more appropriate in a dealloc method if your setter has custom logic.
not all getters take this form:
- (id)variable { return variable; }
...that is merely the most primitive form. properties alone should suggest more combinations, which alter the implementation. the primitive accessor above does not account for idioms used in conjunction with memory management, atomicity, or copy semantics. the implementation is also fragile in subclass overrides.
some really brief examples follow; things obviously become more complex in real programs where implementations become considerably more complex.
1) the getter may not return the instance variable. one of several possibilities:
- (NSObject *)a { return [[a copy] autorelease]; }
2) the setter may not retain the instance variable. one of several possibilities:
- (void)setA:(NSObject *)arg
{
...
a = [arg copy];
...
}
3) you end up with memory management implementation throughout your program, which makes it difficult to maintain. the semantics of the class (and how it handles instance variables' ref counting) should be kept to the class, and follow conventions for expected results:
- (void)stuff:(NSString *)arg
{
const bool TheRightWay = false;
if (TheRightWay) {
NSMutableString * string = [arg mutableCopy];
[string appendString:#"2"];
self.a = string;
[string release];
// - or -
NSMutableString * string = [[arg mutableCopy] autorelase];
[string appendString:#"2"];
self.a = string;
}
else {
NSMutableString * string = [arg mutableCopy];
[string appendString:#"2"];
self.a = string;
[self.a release];
}
}
failing to follow these simple rules makes your code hard to maintain and debug and painful to extend.
so the short of it is that you want to make your program easy to maintain. calling release directly on a property requires you to know a lot of context of the inner workings of the class; that's obviously bad and misses strong ideals of good OOD.
it also expects the authors/subclassers/clients to know exactly how the class deviates from convention, which is silly and time consuming when issues arise and you have to relearn all the inner details when issues arise (they will at some point).
those are some trivial examples of how calling release on the result of a property introduces problems. many real world problems are much subtler and difficult to locate.

Subclassing in Objective-C

I'm a bit new to Objective-C, and I've been trying to do something that apparently isn't allowed, even though it's common practice in other languages (I think).
As a specific example, I want to subclass NSMutableArray to make a SortedMutableArray that always maintains itself in a sorted state. So I subclassed NSMutableArray in the usual manner, adding a NSComparator property that determines the sort order. I overrode the addObject: method to insert objects in a sorted manner:
- (void) addObject:(id)anObject {
for (int i = 0; i < [self count]; ++i) {
NSComparisonResult result = (NSComparisonResult)self.comparator([self objectAtIndex:i], anObject);
if (result == NSOrderedDescending || result == NSOrderedSame) {
[super insertObject:anObject atIndex:i];
break;
}
else {
if (result != NSOrderedAscending) {
[NSException raise:#"InvalidBlockException" format:#"Block must return one of NSOrderedDescending, NSOrderedAscending, or NSOrderedSame"];
}
}
}
}
and everything compiles great. But when I run the program, I get an error indicating that insertObject:atIndex: is now abstract and needs to be implemented. Reading the documentation, it lists several methods that must be implemented in any subclass of NSMutableArray, one of which is indeed insertObject:atIndex:. But I don't need to change the functionality of insertObject:atIndex:; I want it to word exactly as it does in NSMutableArray. Is there a way that I can do this (in general, too, not just for this specific problem)? Why must certain methods be implemented in subclasses like this? Doesn't that kind of defeat one of the purposes of inheritance, code reuse? I've never seen anything like this in other languages, where a method is concrete in a superclass but becomes abstract when it is subclassed. Does this pattern/concept have a name?
Thanks in advance for any help, and I'm sorry if I'm duplicating another question, but I didn't know what to search for other than "subclass" in the objective-c tag, which gave too many results to find what I was looking for.
Bad idea. NSArray is actually a class cluster (which is our word for [essentially] an abstract factory). This means that when you alloc/init an NSArray, you don't actually get an NSArray back. You get (usually) an NSCFArray, which is a private subclass.
NSMutableArray is the same deal (it's abstract). When you alloc/init an NSMutableArray, you get an NSCFArray back that has a little internal mutable bit flipped.
The upshot of this is that subclass a class cluster is generally discouraged, because it's a bit more complex than just creating a normal subclass.
What I would recommend is to instead check out the CHDataStructures framework, which has a whole bunch of data structures that do what you're looking for already.
See Dave DeLong's post about why this is a not a good idea.
If you really want to do something like this, you could try, uhmm, "fake-subclassing" it.
in the .h file,
...
NSMutableArray *mutableArray;
...
#property (nonatomic, retain) NSMutableArray *mutableArray;
...
- (void) addObject:(id)anObject;
in the .m file,
...
#synthesize mutableArray;
...
- (void) addObject:(id)anObject {
[mutableArray addObject:id];
[mutableArray sortUsingSelector:#selector(yourSortingSelector);
}
- (NSMutableArray)mutableArray {
return mutableArray;
}
...
Which works and everything. My colleague did a similar class to this before (we were objective-c noobs at the time, about 2-3 weeks into learning how to code).
What I would recommend, however, is to use a Key-Value Observing approach if you can. Try to listen in whenever an element is added, and sort your array when you get the notification. I haven't done this to an NSMutableArray before though, so I don't know how this will work or if it even will.
My 2 cents, hope it helps. Happy holidays! ^_^
You shouldn't be subclassing NSMutableArray, look up categories. It provides a way to add newer methods to classes
apple's link to categories