How exactly getter and setter methods body looks like after they have been automatically synthesized ?
From official documentation I found so far only recommended implementation techniques, however no word about which of them used by compiler during synthesizing process: http://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmAccessorMethods.html#//apple_ref/doc/uid/TP40003539-SW5
Some techniques recommends implementations containing autorelease message, which is not quite secure for multithreaded programming. I'm just wonder if auto-generated code follows to some of the proposed implementations.
For example:
.h
@interface AClass: NSObject{}
@property (nonatomic, retain) AnotherClass *aProp;
@end
.m
@implementation AClass
@synthesize aProp
-(id) init {
if ((self = [super init])) {
self.aProp = [[AnotherClass alloc] init]; // setter invocation
}
return self;
}
-(AnotherClass *) aMethod {
return self.aProp; // getter invocation
}
@end
What are equivalent accessors code snippets for aProp generated by compiler ?
-(AnotherClass *) aProp {
// getter body
}
-(void) setAProp: (AnotherClass *) {
// setter body
}
When declaring a property as nonatomic, you'll get the following:
// .h
@property (nonatomic, retain) id ivar;
// .m
- (id)ivar {
return ivar;
}
- (void)setIvar:(id)newValue {
if (ivar != newValue) { // this check is mandatory
[ivar release];
ivar = [newValue retain];
}
}
Note the check ivar != newValue. If it was absent, ivar could be dealloc'ed after release, and the following retain would cause a memory access error.
When you declare your property with copy, the code will look almost the same, with retain replaced by copy.
For assign, it is even simpler:
- (void)setIvar:(id)newValue {
ivar = newValue;
}
Now, when you declare your property as atomic (this one is the default), things get slightly more complicated. A snippet similar to the one below was posted by one of Apple's engineers on the development forums:
- (id)ivar {
@synchronized (self) {
return [[self->ivar retain] autorelease];
}
}
- (void)setIvar:(id)newValue {
@synchronized (self) {
if (newValue != self->ivar) {
[self->ivar release];
self->ivar = newValue;
[self->ivar retain];
}
}
}
Note the @synchronized block in both methods and additional retain-autorelease in the getter. Both those things ensure that you will either get the previous value (retained and autoreleased) or a new one in the case the value is changed by some thread while you are trying to read it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With