This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Atomic vs nonatomic properties
I just want to know what is the differneve between theses two lines of code :
#property(nonatomic, retain) NSString *str;
and
#property(atomic, retain) NSString *str;
Thanx,
Regards,
tek3
Atomic properties are necessary in a reference counted multi threaded environment in order to stop objects from disappearing before a thread has a chance to retain them.
Consider the naive implementation of a get accessor:
#interface MyObject : NSObject
{
id myPropertyIVar;
}
-(id) myProperty;
#end
#implementation MyObject
-(id) myProperty
{
return myPropertyIvar;
}
// other stuff
#end
This is all fine except that if you release the instance of MyObject before retaining the returned value from -myProperty the returned value may well be deallocated. For this reason, it is safer to implement -myProperty like this:
-(id) myProperty
{
return [[myPropertyIvar retain] autorelease];
}
This is now completely safe in a single threaded environment.
Unfortunately, in a multithreaded environment there is a race condition. If the thread is interrupted at any time before the retain has incremented the retain count, either of the following will cause you to receive a garbage pointer:
the instance of MyObject is released and deallocated by another thread causing the ivar to be released and deallocated
myProperty is reassigned by another thread causing the old version to be released and deallocated
For this reason, all accesses to the property must be protected by a lock. The get accessor looks something like this.
-(id) myProperty
{
// lock
return [[myPropertyIvar retain] autorelease];
// unlock
}
The set accessor is similarly protected and so is the release in -dealloc
The Apple docs explain all this very well. To learn about properties, including their atomicity, read this page.
Related
Today I was at interview and was asked a question:
Generate setter and getter by hands for proper declaration using manual reference counting:
#interface SomeClass : NSObject
{
NSMutableArray* _array;
}
#property (copy) NSArray* array;
#end
My answer was:
- (NSArray *)array
{
#syncronized (self)
{
return [_array copy];
}
}
- (void)setArray:(NSArray *)array
{
#synchronized (self)
{
if (_array != array)
{
[_array release];
_array = [array mutableCopy];
[_array retain]
}
}
}
I never worked using MRC so not sure about correctness of an answer. Please help me to correct this code with description!
I am the author of one of the linked topics and I think now I understand MRC enough to write this answer here:
1) You're obviously leaking the copy in the getter (see it also in the comments) - so it should be balanced by corresponding autorelease call.
Also note, that this copy inside your getter is done because of you need to return immutable object, not because of getters for #properties declared with (copy) require you to do so!
2) Your setter should not retain after mutableCopy, since mutableCopy already does +1 for you.
See the following quotes from Advanced Memory Management Programming Guide
Basic Memory Management Rules.
You own any object you create
You create an object using a method whose name begins with “alloc”, “new”, “copy”, or “mutableCopy” (for example, alloc, newObject, or mutableCopy).
And
Ownership Policy Is Implemented Using Retain Counts
The ownership policy is implemented through reference counting—typically called “retain count” after the retain method. Each object has a retain count.
When you create an object, it has a retain count of 1.
3) In my topic's comments #robmayoff shared the link to open source implementation of runtime: reallySetProperty in objc-accessors.mm with the following reasoning behind it:
The nonatomic retain and copy setters unfortunately have an unnecessary race condition. If, on thread 1, the setter releases _count, and on thread 2 the getter accesses _count before thread 1 has set _count = [count retain], thread 2 may access a deallocated object. Always store the new value in _count before releasing the old value. The real accessor in the Objective-C runtime does it correctly. See reallySetProperty in objc-accessors.mm. – rob mayoff
4) You example is also missing dealloc since you were to write it under MRC.
5) [IMO, maybe subjective] Since your setter is creating copies of array argument, you don't need to have this if (_array != array) check since the task of (copy) setter is, I believe, to produce copies of what is passed, so I think this is may be omitted.
Having these points in mind I would write your example like the following:
- (NSArray *)array
{
id array;
#synchronized (self)
{
array = [_array copy];
}
return [array autorelease];
}
- (void)setArray:(NSArray *)array
{
id oldValue;
#synchronized (self)
{
oldValue = _array;
_array = [array mutableCopy];
}
[oldValue release];
}
- (void)dealloc {
[_array release];
[super dealloc];
}
In answer to your question in the comments:
Is it normal and really can be used in the daily practice?
I would say, that it can be used in a daily practice with the following additional considerations:
1) You should move you ivar declaration into a private category #interface SomeClass () be it inside your .m file or a private class extension.
2) You should make your getters/setters nonatomic since atomicity of this property is on your shoulders (you already do synchronized on your own in both setter and getter).
3) See also the setup from linked topic which omits ivar and uses second #property declaration. In your case it would look like this:
// .h
#interface SomeClass : NSObject
#property (nonatomic, strong, readonly) NSArray *array;
#end
// .m or private class extension
#interface SomeClass()
#property (nonatomic, strong) NSMutableArray *array;
#end
#implementation SomeClass
// and here your getters/setters
#end
This setup looks promising though I haven't really tested it for the case like yours.
P.S. Recently I did some research for this back-to-the-past Manual Reference Counting, let me share with you the following links which I found to be the best on this topic:
Advanced Memory Management Programming Guide (this is the MUST)
An In-depth Look At Manual Memory Management In Objective-C (this one too!)
What clang taught us about Objective-C properties
Memory and thread-safe custom property methods
Source code of objc runtime.
I realize that it automatically creates a setter & getter for you but I'm uncertain how the setter actually "looks".
Also, why is it recommended that we say #synthesize someObject = _someObject; instead of just #synthesize someObject;?
Easy bit first: you don't need to #synthesize at all any more. If you have an #property and you don't synthesise it then one is implied, of the form #synthesize someObject = _someObject;. If you left off the = _someObject then you would have the same thing as #synthesize someObject = someObject;. The underscore version is therefore preferred because Apple has swung back to advocating underscores for instance variables and because it's consistent with the implicit type of synthesise.
The exact form of setter and getter will depend on the atomic, strong, unsafe_unretained, etc flags but sample nonatomic strong setter, pre-ARC is:
- (void)setProperty:(NSString *)newPropertyValue
{
[newPropertyValue retain];
[_property release];
_property = newPropertyValue;
}
Note the retain always occurs before the release. Otherwise the following (which you would arrive at in a roundabout fashion rather than ever writing directly):
self.property = _property;
Would lead to _property potentially being deallocated before it was retained.
A sample getter (also pre-ARC) is:
- (NSString *)property
{
return [[property retain] autorelease];
}
The retain ensures that the return value will persist even if the object it was queried from is deallocated. The autorelease ensures you return a non-owning reference (ie, the receiver doesn't explicitly have to dispose of the thing, it can just forget about it when it's done). If the thing being returned is immutable but the instance variable is mutable then it's proper form to copy rather than retain to ensure that what you return doesn't mutate while someone else is holding onto it.
Check leture 3 of iPad and iPhone Application itunes
_someObj replace a memory location for store your object(a pointer).
Xcode 4 auto #synthesize anyObject = _anyObject; -> So you don't need to write #synthesize anymore.
If you have some other object or _anyMemoryLocation write before in your.m file, you can use #synthesize yourObj = _anyMemeryLocation if you don't want rewrite all name in your.m file.
Setter and getter 2 methods use to set or get your object's value outside or inside your class:
-(void)setObject:(ObjectType *) object;
-(void)getObject:(ObjectType *) object;
The key nonatomic auto generate setter and getter for you.
If you want to implement more method went setObject, you can rewrite it in your.m file
-(void)setObject:(ObjectType *) object{
_object = object; //rewrite setter can done anywhere in your.m file
//Add more method
}
In the following common sample,
////
#interface MyObject : NSObject
{
#public
NSString * myString_;
}
#property (assign) NSString * myString;
#end
#implementation MyObject
#synthesize myString = myString_;
#end
////
why declare myString_ in the interface at all?
I ask because we can still get and set myString in the implementation using self.myString, [self myString], self.myString = ... and [self setMyString:...] and in fact we must if instead it's being retained.
This is a matter of preference/convention for some. By default, doing:
#property (assign) NSString * myString;
...followed by:
#synthesize myString;
...will give you three things. You get a setter method that can be accessed as self.myString = #"newValue" or [self setMyString:#"newValue"], a getter method that can be accessed as NSString* temp = self.myString or NSString* temp = [self myString], and an instance variable named myString that be be accessed directly inside of your class (i.e. without going through the getter and setter) and used to set and get the property value, and which is used internally to back the property.
If you like you can do #synthesize myString = someOtherVarName, and then you still get the setters and getters just as before, but instead of the myString instance variable the someOtherVarName instance variable is used to back the property, and no myString variable is created.
So why ever use the more verbose syntax? There is never any case that requires that you do so, but some people prefer to do so when dealing with properties that are declared retain or copy. The reason for this being that setting a property declared retain or copy via its generated setter method will affect the retain-count of the object being set/unset. Doing the same thing by accessing the instance variable directly will not.
So by aliasing the instance variable to something else, you can make a distinction in the code along the lines of "anything that does xxx.myString = Y is modifying the retain count, while anything that does someOtherVarName = Y is not". Again, it's not necessary to do this, but some people prefer to.
You should be able to skip it. Modern compilers allow that.
When you define a property, you are actually declaring how the getter and setter methods are constructed for a particular instance variable. Earlier it needed the instance variable to be defined so you declared it. It also allowed the property name to differ from the instance variable name via #synthesize myProperty = myIVar;. Now you don't need to do this as the modern compilers generate the instance variable for you.
The dot syntax is actually a convenience thing as you would've noticed. It doesn't directly refer to the instance variable but the methods myProperty and setMyProperty:. You can even call myArray.count where count isn't a property (I wouldn't recommend it even though lot of people seem to like it).
While there is a difference between the two, the gap seems to be slowly closing.
That's just a problem about point of view. If you access ivar directly, it's you're accessing it internally. If you're using property, you're not accessing ivar (semantically). You're using accessing method of the object. So you're handling the self as like external object which the internal is unknown.
This is encapsulation problem of Object-Oriented paradigm.
And I recommend some tricks when using properties.
The ivar declaration is optional, not required. Compiler will generate it automatically.
You should set the ivar as #protected or #private to encapsulate it correctly. (at least there is no reasonable reason)
I recommend to use nonatomic if you don't need threading lock when accessing the property. Threading lock will decrease performance greatly, and may cause strange behavior in concurrent execution code.
You can use this code to do same thing.
#interface MyObject : NSObject
#property (assign,nonatomic) NSString * myString;
#end
#implementation MyObject
#synthesize myString;
#end
And this will be transformed roughly something like this.
#interface MyObject : NSObject
{
#private
NSString* myString; // Ivar generated automatically by compiler
}
#end
#implementation MyObject
// Methods with thread synchronization locking generated automatically by compiler.
- (NSString*)myString { #synchronized(self) { return myString; } }
- (void)setMyString:(NSString*)newMyString { #synchronized(self){ myString = newMyString; } }
#end
In fact, I'm not sure about synchronization lock with assign behavior directive, but it's always better setting it nonatomic explicitly. Compiler may optimize it with atomic operation instruction instead of locking.
Here is reference document about the properties: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html%23//apple_ref/doc/uid/TP30001163-CH17
With the modern Obj-C runtime, declaring the ivar is more of a formality than anything else. However, there are some memory management things to keep in mind.
First, the property declaration for an object type is usually retain, or for strings it may be copy. In either case, the new object is retained.
Given the following code:
NSString *string = [[NSString alloc] init];
myString_ = string;
self.myString = string; // If the property was retain or copy
The second assignment would leak; the first would not. This is because the property would retain something that already has a retain count of 1—it is now at 2. When you release the property in dealloc, the count goes to 1, not 0, so it won't be released. With the first option, however, the retain count stays at 1, so dealloc brings it down to 0.
In your example, leaving the property as assign will make the ivar declaration a formality.
I have the following code for a property whose getter/setter I write manually using the #dynamic keyword:
#property (nonatomic, retain) NSObject* obj;
#dynamic obj;
-(NSObject*) obj
{
return obj;
}
-(void) setObj:(NSObject*)newObj
{
[obj release];
obj = [newObj retain];
}
My question is, if I remove the retain from the #property declaration, the compiler complains that the default will be assign and that it may not be what I want. If I add the retain, I assume it is going to be ignored, because I wrote the getters/setters myself?
Just looking for a quick confirmation on this.
You are correct, but your property declaration is as much for documentation as it is for your implementation, at least in this case. At some point, someone (you in six months?) will look at your .h file and say, "Why isn't this value being retained? How does this not crash every time it gets run or leak memory like a sieve?"
The retain allows your object to stay allocated in memory until you apply
[obj release];
so even if you do have your own setter and getter you need to keep the retain to keep your place in memory, because in the end you only have a pointer to that position and that is why the compiler tels you that you may modifying another object or what ever takes the place of your object.
And its important that you make the release to free the memory when you are done using it.
I am trying to understand what is happening in the getter below, this is what I understand so far:
(1) the getter returns a pointer to an NSString object. (2) the NSString object is retained, possibly because we have just given away a pointer to it. (3) autorelease? when does that activate, when the PlanetClass instance is deallocated (released)?
// CLASS
#interface PlanetClass : NSObject {
NSString *planetName;
}
- (NSString *)planetName;
- (void)setPlanetName:(NSString *)value;
#end
// GETTER
- (NSString *)planetName{
return[[planetName retain] autorelease];
}
EDIT: I think I am more confused regarding the reason for the actual retain and later release. my understanding was that the getter simply returned a pointer to either nil or an object that already exists (i.e. was set by the setter) I think I understand the retain as we are giving away a pointer and we need to track that, but what about the release, is that just a failsafe incase I later forget to release the NSString object?
The instance variable planetName is also release in my dealloc method (see below) autorelease seems to be doing the same, just later when the pool is drained?
- (void)dealloc {
[planetName release];
[super dealloc];
}
cheers -gary-
It might be a good idea to let Objective-C handle this as a property, letting you clean up some of the implementation to keep the memory management, well, manageable:
#interface PlanetClass : NSObject {
NSString* planetName;
}
#property(nonatomic, retain) NSString* planetName;
#end // PlanetClass
#implementation PlanetClass
#synthesize planetName
//... rest of PlanetClass here
#end // PlanetClass
There are plenty of docs available online for more details on Objective-C properties and #synthesize.
Memory Management Docs
I highly recommend this read from Apple on memory management to try and help understand what all the retain/release hubbub is about.
When autorelease is sent to an object, it is added to the autorelease pool. When the pool is drained, it sends release to all the objects in the pool. So any object in the autorelease pool will be release when the pool is drained
The return/autorelease in the getter method is not doing anything, you can just return planetName