Reputation: 4017
Can anyone explain the difference between setting someObject = someOtherObject;
and self.someObject = someOtherObject;
if someObject is a class property created with @property (nonatomic, retain) SomeType someObject;
To clarify I have something like:
@interface SomeClass : NSObject {
SomeType* someObject;
}
@property (nonatomic, retain) SomeType* someObject;
@end
I have noticed I get EXC_BAD ACCESS sometimes when I use the property without self and it seems quite random. When I use self my program acts as it should be. I don’t get any compiler errors or warnings when I skip self so I guess it is somehow valid syntax?
Upvotes: 5
Views: 673
Reputation: 16709
Properties are just a convenient way to access the data. So when you are declaring the property @property (nonatomic, retain) SomeType* someObject; this means that during access there would be synthesized 2 methods:
getter:
-(SomeType*) someObject {
return someObject;
}
setter
-(void) setSomeObject:(SomeType*) obj {
[someObject release];
someObject = [obj retain];
}
So the main difference between properties and ivars is that properties dynamically creating the setter/getter methods (and you can override them). But when you're writing someObject = new_val, you're just copying the reference to the memory location. No additional work is done there except one assembly instruction.
There is one more thing to mention: atomic and nonatomic. With atomic, the synthesized setter/getter will ensure that a whole value is always returned from the getter or set by the setter, regardless of setter activity on any other thread. That is, if thread A is in the middle of the getter while thread B calls the setter, an actual viable value -- an autoreleased object, most likely -- will be returned to the caller in A.
In nonatomic, no such guarantees are made. Thus, nonatomic is considerably faster than atomic.
Edit: so if you have some variable, that is accessed from different threads or/and some additional work has to be done (e.g. retain, raise some flags ...), then your choice is property. But sometimes you have a variable, that is accessed very often and access via property can lead to a big overhead, because processor has to perform much more operations to synthesize and call method.
Upvotes: 2
Reputation: 11784
It's all about memory management.
Your class property someObject
have generated accessors with annotation @property
/ @synthsize
in your .h / .m files.
When you are accessing you property with someObject
, you directly access the property. When you are accessing self.someObject
you are calling your accessor [self someObject]
whitch take care of memory management for you.
So when you need to assign a class property it's cleaner to do self.someObject = someOtherObject;
because you use the setter and does not have to take care about releasing and retaining. When your setter is generated with @property (nonatomic, retain)
so it will take care about retaining for you.
Upvotes: 1
Reputation: 5432
The difference between the two is:
1) when you do not use "self." you are assigning the result directly to the member variable.
2) when you are using "self." you are calling the setter method on that property. It is the same as [self setMyObject:...];
so in case of self.myobject, it keeps its retain, and in other case, (without self), if you are not using alloc, then it will be treated as autoreleased object.
In most cases you will find you want to use "self.", except during the initialization of the object.
By the way, you can also use self.someObject = [someOtherObject retain]
to increase retain counter
Upvotes: 0
Reputation: 10009
self.someObject = someOtherObject
makes use of the property. Properties generate setters and getters for you. In your case, you gave the retain
attribute to the property, which means that an object set via this property will automatically receive a retain
message which increases its retain count by 1. Additionally, the old value of the member variable is sent a release
message which decreases its retain count.
Obects are being deallocated, when their retain count reaches 0. You get an EXC_BAD_ACCESS ecxeption if you try to access a deallocated object (e.g. if you try to release it too often).
In your case:
SomeOtherObject *soo = [[SomeOtherObject alloc] init]; //retain count: 1
self.someObject = soo; //soo's retain count is now 2
[soo release]; //soo's retain count is 1 again, as self still uses it.
[self doSomethingWithSoo];
However, if you do not use the setter, you must not release soo
.
SomeOtherObject *soo = [[SomeOtherObject alloc] init]; //retain count: 1
someObject = soo; //soo's retain count is still 1
[soo release]; //soo's retain count is 0, it will be deallocated
[self doSomethingWithSoo]; //will fail with an EXC_BAD_ACCESS exception, as soo does not exist anymore.
Upvotes: 5