objective-c和内存管理中的类变量

时间:2011-08-22 07:18:58

标签: iphone objective-c memory-management

@implementation ProductController


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

@implementation ProductController


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

现在哪一个是正确的?为什么?

2 个答案:

答案 0 :(得分:5)

如您所知,Obj-C中没有“类变量”。解决方法只是一个C风格(全局或文件范围)变量,您设置的变量与上面显示的相似。首先,您应该使用static关键字标记这些变量的文件范围:

static NSString *areaName = nil;

您也可以考虑使用FirstLetterUppercase这样的约定来表示范围差异。

至于内存管理,你可以将它看作一个实例变量,但它永远不会永远消失:

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

请注意,在第二个示例中,您不应该从实例的-dealloc方法中释放“class”变量。如果你有多个对象的实例,这会留下一个糟糕的悬空指针,并且无论如何都会破坏“类”变量的目的。通常,当您使用此模式时,您将“泄漏”(对于某些泄漏定义)类变量值,这没关系。

答案 1 :(得分:0)

类变量通常都是不好的样式。

然而,其他答案的替代方法是为lib / app的类变量创建静态字典。一个非常原始的实现将采用这种形式:

// 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