What does this mean? “Writable atomic property 

2019-05-24 11:36发布

问题:

Possible Duplicate:
error: writable atomic property cannot pair a synthesized setter/getter with a user defined setter/getter

I have a header file where I declare an atomic property, like this:

@property (retain) FileManager *fileManager;

Then I synthesize that in the implementation file:

@synthesize fileManager;

And then I write my own accessor for lazy initialization:

- (FileManager*)fileManager {
    if (fileManager) {
        return fileManager;
    }

    FileManager *fm = [[FileManager alloc] init];
    self.fileManager = fm;
    [fm release];

    return fileManager;
}

Everything works perfectly and Xcode 3.2 never complained. But Xcode 4 warns:

Writable atomic property 'fileManager' cannot pair a synthesized setter/getter with a user defined setter/getter

When I get that right it is trying to say: "You cannot overwrite synthesized getters/setters like you did the past 3 years, even though it worked perfectly!"

Obviously surpressing warnings is stupid. This property really needs to be thread-safe, and I really want this lazy initialization. What am I supposed to do now?

Edit: According to this question and answer on SO, the @synchronize code is missing here. How would I make this accessor properly thread-safe by hand?

I tried rewriting it to this:

- (FileManager*)fileManager {
    @synchronized(self) {
        if (fileManager) {
            return fileManager;
        }

        FileManager *fm = [[FileManager alloc] init];
        self.fileManager = fm;
        [fm release];


        return fileManager;
    }
}

But the warning doesn't go away. So when I get the answer of that other question right, the only way to get rid of this warning is to either not customize synthesized atomic property accessors or to omit the @synthesize completely and do it all by hand: The accessor AND the mutator. Of course, this would suck. Is there a better solution to the problem?

What does it mean if I set it to @dynamic fileManager instead of @synthesize fileManager?

Edit: So I tried using @dynamic instead of @synthesize. It really means to implement both accessor and mutator manually. Then why would I even want to declare it as @dynamic at all?

回答1:

If you declare an @property that is atomic -- the default -- you must either use @dynamic, let the compiler @synthesize everything or provide an implementation of both the setter and getter.



回答2:

You could use the pattern for lazy initialization illustrated in many of the Apple code examples in past years. There is typically a corresponding local variable, by convention with a leading underscore (_). In the @synthesize statement you assign it to the ivar:

@synthesize fileManager = _fileManager;

and you lazily create the local variable.

-(FileManager) fileManager {
   if (_fileManager != nil) return _fileManager;
   // etc...
}