0
@implementation ProductController


NSString *areaName = nil;
+ (void)setAreaName:(NSString *)areaName_ {
    areaName = areaName_;
}
@end

and

@implementation ProductController


NSString *areaName = nil;
+ (void)setAreaName:(NSString *)areaName_ {
    if(areaName_ != areaName) {
        [areaName release];
        areaName = [areaName_ copy];
    }
}
- (void)dealloc {
     [areaName release];
}
@end

Now which one is correct?and why?

1
  • 3
    Don't forget -[super dealloc]! Commented Aug 22, 2011 at 7:24

2 Answers 2

5

As you seem to understand, there are no "class variables" in Obj-C. The workaround is just a C-style (global, or file-scoped) variable that you set up similarly to how you've shown above. First off, you should use file scope for these variables by marking them with the static keyword:

static NSString *areaName = nil;

You might also consider using a convention like FirstLetterUppercase to indicate the scope difference.

As for memory management, you can treat it exactly like an instance variable, but one that never goes away forever:

static NSString *AreaName = nil;
+ (void)setAreaName:(NSString *)name {
    if (![name isEqualToString:AreaName]) {
        [AreaName release];
        AreaName = [name copy];
    }
}

Note that in your second example, you should NOT release the "class" variable from an instance's -dealloc method. If you have more than one instance of the object, this leaves a bad dangling pointer, and defeats the purpose of the "class" variable anyways. Generally, when you use this pattern, you'll "leak" (for some definition of leak) the class variable value, and that's OK.

Sign up to request clarification or add additional context in comments.

4 Comments

+1 for looking beyond the simple assignment-vs-retain/release and noticing the actual question, unlike the other two answers (including mine) :)
Hmmm... isEqualToString: prevents needless copying, so far so good, but the comparison is probly not cheap either. I'd prefer the original, checking for identity, since that is what you want to know before you release and re-assign.
Yes, that should be it.But is it ok not to use "static"? Because it seems to work fine as a global variable.And thanks for pointing out the rookie mistakes. :)
@Carusd Ray: It does work when you don't use "static", but when you don't, the global is accessible to the rest of your program. That is both unnecessary and can cause naming conflicts, so you should use "static" in this case.
0

class variables are generally bad style.

nevertheless, an alternative to other answers would be to create a static dictionary for your lib/app's class variables. a very primitive implementation would take this form:

// MONLibraryClassVariable.h

extern id MONLibraryClassVariableGetObjectForKey(NSString * key);
extern void MONLibraryClassVariableSetObjectForKey(id<NSObject> object, NSString * key);

// MONLibraryClassVariable.m

/* @todo make all this thread safe */

static NSMutableDictionary * MONLibraryClassVariables_ = nil;

id MONLibraryClassVariableGetObjectForKey(NSString * key) {
    return [MONLibraryClassVariables_ objectForKey:key];
}

void MONLibraryClassVariableSetObjectForKey(id<NSObject> object, NSString * key) {

    if (nil == MONLibraryClassVariables_) {
        MONLibraryClassVariables_ = [NSMutableDictionary new];
    }

    [MONLibraryClassVariables_ setObject:object forKey:key];
}

// ProductController.m

static NSString * const ProductController_KEY_areaName = @"ProductController.areaName";

@implementation ProductController

+ (void)setAreaName:(NSString *)inAreaName {
    MONLibraryClassVariableSetObjectForKey([[inAreaName copy] autorelease], ProductController_KEY_areaName);
}

- (void)dealloc {
// nope [areaName release];
    [super dealloc];
}

@end

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.