3

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
}
Martin Babacaev
  • 6,240
  • 2
  • 19
  • 34

2 Answers2

8

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.

Alexei Sholik
  • 7,287
  • 2
  • 31
  • 41
  • ei how do you know if the compiler will generate implementation based on [technique3](http://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmAccessorMethods.html#//apple_ref/doc/uid/TP40003539-SW8) ? – Martin Babacaev Mar 18 '11 at 10:59
  • @Martin The compiler doesn't use any of the techniques given in that doc. Those techniques are for humans implementing their own getters and setters. The compiler, on the other hand, will synthesize properties directly into object code. So, the code given in my answer is just a high level model of what the compiler might do if it generated ObjC code as text. It should be sufficient for understanding the principle of how synthesized properties work. If you would like to get a more definite answer, you could look at how the code generation is implemented in, say, LLVM compiler. – Alexei Sholik Mar 18 '11 at 12:15
  • ei how can I obtain these intermediate result with accessories body implemented (in C, Assembler) ? With conceptual level I'm already familiar, the compiler version - that what I actually looking for. – Martin Babacaev Mar 18 '11 at 12:34
  • @Martin Lookup man page for clang. It has an `-S` option to generate assembly output. – Alexei Sholik Mar 18 '11 at 12:53
  • what about KVO stuff? – OrangeDog Mar 31 '14 at 16:40
0

It depends on the attributes you set, for instance with a RETAIN attribute...

- (void)setAProp:(AnotherClass *)value {
   [aProp release];
   aProp = value;
   [aProp retain];
}

For ASSIGN attribute....

- (void)setAProp:(AnotherClass *)value {
   aProp = value;
}

For COPY attribute (used with NSString)...

- (void)setAProp:(AnotherClass *)value {
   aProp = [value copy];
}
Simon Lee
  • 22,304
  • 4
  • 41
  • 45
  • 2
    Yes, it depends on the attributes, but we don't know how Apple implements it and we should not care. Also, the example you have for retain has a bug. If you assign the same value that was already assigned, then the object will be deallocated because the retain count reaches 0. To avoid this a setProp would usually check if the same value is set again. You can see more details here: http://cocoawithlove.com/2010/06/assign-retain-copy-pitfalls-in-obj-c.html – Kobski Mar 18 '11 at 10:39
  • @Kobski we do care if we are in a thread other than main, because 2 recommended techniques uses `autorelease`: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmAccessorMethods.html#//apple_ref/doc/uid/TP40003539-SW5 – Martin Babacaev Mar 18 '11 at 10:41
  • If you don't specify "nonatomic", then the getter and setter functions will be thread safe. – Kobski Mar 18 '11 at 10:46
  • Atomic properties provide only basic guarantee of data integrity. Each application has to provide it's own strategy for protection of the data shared between multiple threads. – Alexei Sholik Mar 18 '11 at 12:19
  • Also you didn't specify anything about the getters, so no upvote. – SilverSideDown Aug 21 '12 at 15:52
  • Your setAProp method is faulty. It doesn't check for the object being set being a different object to the existing, and if they're the same object, you'll release it before trying to retain it. – occulus Jun 22 '17 at 21:28