Objective-C Memory Management on Static Variables

///**************************
// MyClass.m
#import "MyClass.h"

static MyClass *myClass = NULL;

@implementation MyClass
  • (MyClass *)sharedMyClass {

myClass = NULL;
myClass = [[MyClass alloc] init];
return myClass;
}

@end

Hi Experts, I just want to know myClass is a static ObjC object, it will be automatically released by ARC when no one is referencing it anymore, so no memory leak? is it correct?
Answered by DTS Engineer in 639362022

I just want to know myClass is a static ObjC object, it will be
automatically released by ARC when no one is referencing it anymore,
so no memory leak?

Your conclusion is sound but not for the reasons you’re supposing. A static variable persists until your process is terminated, and thus there’s never a point where “no one is referencing it” (unless you set the static back to nil).

Having said that, your code is a little wonky. I usually write it this way:

Code Block
+ (MyClass *)sharedMyClass {
static MyClass * sShared = nil;
if (sShared == nil) {
sShared = [[MyClass alloc] init];
}
return sShared;
}


There’s two key changes:
  • I put the static within the method to guarantee that no one else is messing with it.

  • You don’t want to allocate a new instance of MyClass on each call, so you have to check to see if the static is nil.

One further gotcha here relates to threading. If +sharedMyClass can be called by multiple threads the check for nil becomes a race condition. If you want to support that case, use dispatch_once.

Code Block
+ (MyClass *)sharedMyClass {
static MyClass * sShared = nil;
static dispatch_once_t sOnceToken;
dispatch_once(&sOnceToken, ^{
sShared = [[MyClass alloc] init];
});
return sShared;
}


ps If you put your code in a code block (using the <> button), it’ll be easier to read.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@apple.com"
Accepted Answer

I just want to know myClass is a static ObjC object, it will be
automatically released by ARC when no one is referencing it anymore,
so no memory leak?

Your conclusion is sound but not for the reasons you’re supposing. A static variable persists until your process is terminated, and thus there’s never a point where “no one is referencing it” (unless you set the static back to nil).

Having said that, your code is a little wonky. I usually write it this way:

Code Block
+ (MyClass *)sharedMyClass {
static MyClass * sShared = nil;
if (sShared == nil) {
sShared = [[MyClass alloc] init];
}
return sShared;
}


There’s two key changes:
  • I put the static within the method to guarantee that no one else is messing with it.

  • You don’t want to allocate a new instance of MyClass on each call, so you have to check to see if the static is nil.

One further gotcha here relates to threading. If +sharedMyClass can be called by multiple threads the check for nil becomes a race condition. If you want to support that case, use dispatch_once.

Code Block
+ (MyClass *)sharedMyClass {
static MyClass * sShared = nil;
static dispatch_once_t sOnceToken;
dispatch_once(&sOnceToken, ^{
sShared = [[MyClass alloc] init];
});
return sShared;
}


ps If you put your code in a code block (using the <> button), it’ll be easier to read.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@apple.com"
Thanks, Eskimo.
The testing code is intentional not for singleton, just want to confirm there is no memory leak if I did so:)
Objective-C Memory Management on Static Variables
 
 
Q