Apple's Memory Management Programming Guide shows three officially sanctioned techniques for writing accessor methods that need to retain or release object references.
In the case of the first two techniques (reproduced below), the Apple documentation says that "[t]he performance of technique 2 is significantly better than technique 1 in situations where the getter is called much more often than the setter."
// Technique 1
- (NSString*) title
{
return [[title retain] autorelease];
}
- (void) setTitle: (NSString*) newTitle
{
if (title != newTitle)
{
[title release];
title = [newTitle retain]; // Or copy, depending on your needs.
}
}
// Technique 2
- (NSString*) title
{
return title;
}
- (void) setTitle: (NSString*) newTitle
{
[title autorelease];
title = [newTitle retain]; // Or copy, depending on your needs.
}
Is this the only difference between technique 1 and technique 2, or does using one over the other have other subtle consequences of which I might need to be aware? And if technique 2 uses a better performing getter, does it follow that technique 1 uses a better performing setter since title gets an explicit (and presumably immediate) release?
The getter from 2 and the setter from 1:
- (NSString*) title
{
return title;
}
- (void) setTitle: (NSString*) newTitle
{
if (title != newTitle)
{
[title release];
title = [newTitle retain]; // Or copy, depending on your needs.
}
}
The second getter is fragile (it will crash if somebody access's the object's title and then releases the object), so the first is generally preferable even if marginally slower.
The first setter is more efficient and will work even in situations where an autorelease pool doesn't exist, so it's preferable. The reason it's more efficient is not just because of autorelease vs. release — it doesn't do any work at all if you try to set the property to its existing value.
Related
I am coding Objective-C using the Cocos2D framework, and I have a singleton used for multiple purposes. One new purposes is to get and set character's "states" which are strings. I've recently made an NSDictionary for this purpose, but I have issues with the program freezing up when a method inside the singleton is called.
Here's the singleton code. I'm just leaving in the character state stuff:
.h
#interface ExGlobal : NSObject {
NSArray *charStates_keys;
NSArray *charStates_objects;
NSMutableDictionary *charStates;
}
#property(nonatomic, retain) NSMutableDictionary *charStates;
+(ExGlobal*)sharedSingleton;
- (NSString *)charState:(NSString *)charName;
- (void)set_charState:(NSString *)value forCharName:(NSString *)charName;
#end
.m
#import "ExGlobal.h"
#implementation ExGlobal
#synthesize charStates;
static ExGlobal* _sharedSingleton = nil;
+(ExGlobal*)sharedSingleton {
#synchronized([ExGlobal class]) {
if (!_sharedSingleton) {
[[self alloc] init];
}
return _sharedSingleton;
}
return nil;
}
+(id)alloc {
#synchronized([ExGlobal class]) {
NSAssert(_sharedSingleton == nil, #"Attempted to allocate a second instance of a singleton.");
_sharedSingleton = [super alloc];
return _sharedSingleton;
}
return nil;
}
-(id)init {
self = [super init];
if (self != nil) {
// initialize stuff here
exitName = #"ruinsSkyMid";
sceneChangeKind = #"reborn";
charStates = [[NSMutableDictionary alloc] init];
charStates_keys = [NSArray arrayWithObjects:#"Feathers", #"Hummus", nil];
charStates_objects = [NSArray arrayWithObjects:#"at wall", #"with Feathers", nil];
charStates = [NSMutableDictionary dictionaryWithObjects:charStates_objects forKeys:charStates_keys];
}
return self;
}
- (NSString *)charState:(NSString *)charName{
NSString *value = [charStates objectForKey:charName];
return value;
}
- (void)set_charState:(NSString *)charState forCharName:(NSString *)charName{
[charStates setObject:charState forKey:charName];
}
- (void)dealloc {
//I know it doesn't get called, but just in case
[charStates release];
[super dealloc];
}
#end
It's unclear to me what exactly the issue is when it freezes. When this happens, all I get in the console is:
Program received signal: “EXC_BAD_ACCESS”.
warning: Unable to read symbols for /Developer/Platforms/iPhoneOS.platform/DeviceSupport/4.3.5 (8L1)/Symbols/Developer/usr/lib/libXcodeDebuggerSupport.dylib (file not found).
Previous frame inner to this frame (gdb could not unwind past this frame)
Previous frame inner to this frame (gdb could not unwind past this frame)
Which I'm sure doesn't help finding the issue. I found if I redefine charStates_keys, charStates_objects and charStates inside both the charState and set_charState methods, it seems to work without freezing, except set_charState does not change the state.
It isn't freezing, it is crashing. Hence the EXC_BAD_ACCESS. It looks like your Xcode installation is borked, too, as the two messages following should not happen.
Note that methods should not have _s in the name; not a cause of the problem, but a comment on following convention.
You aren't retaining charStates and that is likely the cause of the crash.
Not an answer as such but I didn't have enough space in the comments field above to post this, but it might be useful.
As bbum already said, your lack of retaining charStates is likely the problem.
If you are confused about when to retain and not retain objects there's a really good book called "Learn Objective-C on the Mac" and I know it's a Mac book but most of it applies to iPhone too. On page 171 of chapter 9 (Memory Management) it talks about the "Memory Management Rules" and how if you are confused about when to retain or not then you don't understand the simple rules of Objective C memory management.
Essentially if you create an object using new, alloc or copy, then the retain count is automatically set to 1 so the object is retained and does not require you to retain it and will require a subsequent release to deallocate.
If you create the object any other way then the object will be an autoreleased object.
Obviously these rules only apply within the standard iOS libraries and can't necessarily be applied to third party libraries.
I recommend anyone who doesn't fully understand memory management in Objective C read this book. I found highly enlightening even for my iPhone work.
Hope that helps/.
I am learning memory management, but I don't really understand why I should implement my attribute getter like this:
-(Weapon*)myWeapon
{
[myWeapon retain];
[myWeapon autorelease];
return myWeapon;
}
I understand what I wrote, but I can't imagine why it is important? Can you please explain why I should do this?
This is from the Memory Management Programming guide:
Technique 1
In technique 1, values returned by the getter are autoreleased within the calling scope:
- (NSString*) title {
return [[title retain] autorelease];
}
- (void) setTitle: (NSString*) newTitle {
if (title != newTitle) {
[title release];
title = [newTitle retain]; // Or copy, depending on your needs.
}
}
Because the object returned from the get accessor is autoreleased in the current scope, it remains valid if the property value is changed. This makes the accessor more robust, but at the cost of additional overhead. If you expect your getter method to be called frequently, the added cost of retaining and autoreleasing the object may not be worth the performance cost.
Technique 2
Like technique 1, technique 2 also uses an autorelease technique, but this time does so in the setter method:
- (NSString*) title {
return title;
}
- (void) setTitle: (NSString*) newTitle {
[title autorelease];
title = [newTitle retain]; // Or copy, depending on your needs.
}
The performance of technique 2 is significantly better than technique 1 in situations where the getter is called much more often than the setter.
Technique 3
Technique 3 avoids the use of autorelease altogether:
- (NSString*) title {
return title;
}
- (void) setTitle: (NSString*) newTitle {
if (newTitle != title) {
[title release];
title = [newTitle retain]; // Or copy, depending on your needs.
}
}
The approach used by technique 3 is good for frequently called getter and setter methods. It is also good for objects that do not want to extend the lifetime of their values, such as collection classes. Its disadvantage is that the old value may be deallocated immediately (if there are no other owners), which will cause a problem if another object is maintaining a non-owning reference to it. For example:
NSString *oldTitle = [anObject title];
[anObject setTitle:#"New Title"];
NSLog(#"Old title was: %#", oldTitle);
If anObject was the only object that owned the original title string, then the string will be deallocated after the new title is set. The log statement would then cause a crash as oldTitle is a freed object.
EDIT: Basically the point of retaining and then auto-releasing is to ensure that the object won't get deallocated if the property value is changed before the calling scope has a chance to retain it. This isn't usually an issue unless you've got asynchronous code. In most situations - (Weapon *)myWeapon { return myWeapon; } is just fine (plus it's faster).
As ACBurk says, but there is a good description here:
http://vgable.com/blog/2009/03/31/how-to-write-cocoa-object-getters/
I've been reading an apple document on Memory Management and am now a bit confused regarding the recommended implementation of Accessors. Apple cites 3 approaches in implementing accessors.
Technique 1
I've copied the code from the first technique which reflects: "Getter retains and autoreleases the value before returning it; setter releases the old value and retains (or copies) the new value." This first technique is stated to be more robust but suffers performance penalties on frequently called getters.
- (NSString*) title {
return [[title retain] autorelease];
}
- (void) setTitle: (NSString*) newTitle {
if (title != newTitle) {
[title release];
title = [newTitle retain]; // Or copy, depending on your needs.
}
}
skipping Technique 2
Technique 3
The third technique is better for frequently called setters and getters. This is also the method I've always followed.
- (NSString*) title {
return title;
}
- (void) setTitle: (NSString*) newTitle {
if (newTitle != title) {
[title release];
title = [newTitle retain]; // Or copy, depending on your needs.
}
}
My questions are:
(Technique 1) The setter first releases the existing value even if it doesn't point to anything. This would send a message to nil which I understand is supported in Objective-C but still looks odd. Am I understanding this correctly?
(Technique 1) Why is the retain stacked inside an autorelease?
(Technique 1) Is the caller whom uses the getter expected to call release after they're done with the object?
The apple developer documentation page can be found at: Memory Management Programming Guide - Accessor Methods
(Technique 1) The setter first
releases the existing value even if it
doesn't point to anything. This would
send a message to nil which I
understand is supported in Objective-C
but still looks odd. Am I
understanding this correctly?
Yup. Messages to nil matter not.
(Technique 1) Why is the retain
stacked inside an autorelease?
That guarantees that the following doesn't break:
x = [foo title];
[foo setTitle: #"bar"];
[x length]; // x has been released, possibly, if -title didn't retain/autorelease
(Technique 1) Is the caller whom uses
the getter expected to call release
after they're done with the object?
No.
Sending a message to nil is defined to do nothing. This setter is an excellent example of how that allows you to write simpler code: [title release] instead of if (title != nil) [title release];. Note also that no special checks for nil are necessary on newTitle.
The retain/autorelease pair in the getter mean that the returned object will remain valid through the lifetime of the current function call (technically, until the autorelease pool is drained), even if the setter is called. The documentation you cite gives an example of how that can be helpful if there's a variable with a "non-owning reference" to the value.
NO. The value has already been autoreleased; caller must not release it again.
This is a small detail but everytime I lazy load something I get caught up on it. Are both of these methods acceptable? Is either better? Assume that the variable has the retain property.
Method #1
(AnObject *)theObject{
if (theObject == nil){
theObject = [[AnObject createAnAutoreleasedObject] retain];
}
return theObject;
}
Method #2
(AnObject *)theObject{
if (theObject == nil){
self.theObject = [AnObject createAnAutoreleasedObject];
}
return theObject;
}
First, I'm not sure if it's OK to access another accessor function within an accessor (don't see why not, though). But it seems like setting the class variable without going through the setter could be equally bad if the setter does something special (or if the property is changed to something besides retain and the getter isn't checked).
Both are actually quite fragile and not at all identical, depending on what clients of the class are doing. Making them identical is easy enough -- see below -- but making it less fragile is harder. Such is the price of lazy initialization (and why I generally try to avoid lazy initialization in this fashion, preferring to treat initialization of subsystems as a part of overall application state management).
With #1, you are avoiding the setter and, thus, anything observing the change won't see the change. By "observing", I'm specifically referring to key-value observation (including Cocoa Bindings, which uses KVO to update the UI automatically).
With #2, you will trigger the change notification, updating the UI and otherwise exactly as if the setter was called.
In both cases, you have a potential for infinite recursion if the initialization of the object calls the getter. That includes if any observer asks for the old value as a part of the change notification. Don't do that.
If you are going to use either method, consider carefully the consequences. One has the potential to leave the app in an inconsistent state because a state change of a property did not notify and the other has the potential for deadlock.
Better to avoid the issue entirely. See below.
Consider (garbage collection on, standard Cocoa command line tool:
#import <Foundation/Foundation.h>
#interface Foo : NSObject
{
NSString *bar;
}
#property(nonatomic, retain) NSString *bar;
#end
#implementation Foo
- (NSString *) bar
{
if (!bar) {
NSLog(#"[%# %#] lazy setting", NSStringFromClass([self class]), NSStringFromSelector(_cmd));
[self willChangeValueForKey: #"bar"];
bar = #"lazy value";
[self didChangeValueForKey: #"bar"];
}
return bar;
}
- (void) setBar: (NSString *) aString
{
NSLog(#"[%# %#] setting value %#", NSStringFromClass([self class]), NSStringFromSelector(_cmd), aString);
bar = aString;
}
#end
#interface Bar:NSObject
#end
#implementation Bar
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;
{
NSLog(#"[%# %#] %# changed\n\tchange:%#", NSStringFromClass([self class]), NSStringFromSelector(_cmd), keyPath, change);
}
#end
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Foo *foo = [Foo new];
Bar *observer = [Bar new];
CFRetain(observer);
[foo addObserver:observer forKeyPath:#"bar"
options: NSKeyValueObservingOptionPrior | NSKeyValueObservingOptionNew
context:NULL];
foo.bar;
foo.bar = #"baz";
CFRelease(observer);
[pool drain];
return 0;
}
This does not hang. It spews:
2010-09-15 12:29:18.377 foobar[27795:903] [Foo bar] lazy setting
2010-09-15 12:29:18.396 foobar[27795:903] [Bar observeValueForKeyPath:ofObject:change:context:] bar changed
change:{
kind = 1;
notificationIsPrior = 1;
}
2010-09-15 12:29:18.397 foobar[27795:903] [Bar observeValueForKeyPath:ofObject:change:context:] bar changed
change:{
kind = 1;
new = "lazy value";
}
2010-09-15 12:29:18.400 foobar[27795:903] [Bar observeValueForKeyPath:ofObject:change:context:] bar changed
change:{
kind = 1;
notificationIsPrior = 1;
}
2010-09-15 12:29:18.400 foobar[27795:903] [Foo setBar:] setting value baz
2010-09-15 12:29:18.401 foobar[27795:903] [Bar observeValueForKeyPath:ofObject:change:context:] bar changed
change:{
kind = 1;
new = baz;
}
If you were to add NSKeyValueObservingOptionOld to the list of options for observation, it very much does hang.
Getting back to a comment I made earlier; the best solution is to not do lazy initialization as a part of your getter/setter. It is too fine grained. You are far better off managing your object graph state at a higher level and, as a part of that, have a state transition that is basically of the "Yo! I'm going to use this subsystem now! Warm that bad boy up!" that does the lazy initialization.
Those methods are never identical. The first one is right, while the second one is wrong! A getter may never call will/didChangeValueForKey: and therefore also not the setter. This will lead to infinite recursion if that property is observed.
And besides, there is no state change to observe when the member is initialized. You ask your object for the theObject and you get it. When this gets created is an implementation detail and no concern to the outside world.
If you know the property setter method is a standard retaining setter, they're identical. If not, you need to decide whether the setter's other behavior should be invoked during that operation. If you don't know, it's safest to use the setter, since its behavior may be important. Don't sweat it.
Both of those are basically identical, its really just up to you to choose which one is best for your case. You already really described the pros/cons about using the property syntax.
Does #synchronized not use "lock" and "unlock" to achieve mutual exclusion? How does it do lock/unlock then?
The output of the following program is only "Hello World".
#interface MyLock: NSLock<NSLocking>
#end
#implementation MyLock
- (id)init {
return [super init];
}
- (void)lock {
NSLog(#"before lock");
[super lock];
NSLog(#"after lock");
}
- (void)unlock {
NSLog(#"before unlock");
[super unlock];
NSLog(#"after unlock");
}
#end
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
MyLock *lock = [[MyLock new] autorelease];
#synchronized(lock) {
NSLog(#"Hello World");
}
[pool drain];
}
The Objective-C language level synchronization uses the mutex, just like NSLock does. Semantically there are some small technical differences, but it is basically correct to think of them as two separate interfaces implemented on top of a common (more primitive) entity.
In particular with a NSLock you have an explicit lock whereas with #synchronized you have an implicit lock associated with the object you are using to synchronize. The benefit of the language level locking is the compiler understands it so it can deal with scoping issues, but mechanically they behave basically the same.
You can think of #synchronized as a compiler rewrite:
- (NSString *)myString {
#synchronized(self) {
return [[myString retain] autorelease];
}
}
is transformed into:
- (NSString *)myString {
NSString *retval = nil;
pthread_mutex_t *self_mutex = LOOK_UP_MUTEX(self);
pthread_mutex_lock(self_mutex);
retval = [[myString retain] autorelease];
pthread_mutex_unlock(self_mutex);
return retval;
}
That is not exactly correct because the actual transform is more complex and uses recursive locks, but it should get the point across.
In Objective-C, a #synchronized block handles locking and unlocking (as well as possible exceptions) automatically for you. The runtime dynamically essentially generates an NSRecursiveLock that is associated with the object you're synchronizing on. This Apple documentation explains it in more detail. This is why you're not seeing the log messages from your NSLock subclass — the object you synchronize on can be anything, not just an NSLock.
Basically, #synchronized (...) is a convenience construct that streamlines your code. Like most simplifying abstractions, it has associated overhead (think of it as a hidden cost), and it's good to be aware of that, but raw performance is probably not the supreme goal when using such constructs anyway.
Actually
{
#synchronized(self) {
return [[myString retain] autorelease];
}
}
transforms directly into:
// needs #import <objc/objc-sync.h>
{
objc_sync_enter(self)
id retVal = [[myString retain] autorelease];
objc_sync_exit(self);
return retVal;
}
This API available since iOS 2.0 and imported using...
#import <objc/objc-sync.h>
Apple's implementation of #synchronized is open source and it can be found here. Mike ash wrote two really interesting post about this subject:
Locks, Thread Safety, and Swift
Let's Build #synchronized
In a nutshell it has a table that maps object pointers (using their memory addresses as keys) to pthread_mutex_t locks, which are locked and unlocked as needed.
It just associates a semaphore with every object, and uses that.