Objective-C 静态类级别变量

我有一个类 Film,每个类都存储一个唯一的 ID。在 C # ,Java 等等中,我可以定义一个静态的 int currentID,每次我设置 ID 的时候,我可以增加 currentID,变化发生在类级别而不是对象级别。这能在 Objective-C 中完成吗?我发现很难找到这个问题的答案。

159391 次浏览

在.m 文件中,可以将变量声明为 static:

static ClassName *variableName = nil;

然后可以在 +(void)initialize方法上初始化它。

请注意,这是一个普通的 C 静态变量,不是 Java 或 C # 意义上的静态变量,但会产生类似的结果。

正如 pgb 所说,没有“类变量”,只有“实例变量”执行类变量的 Objective-c 方法是在。类的 m 文件。“ static”确保变量不能在该文件之外使用(也就是说,它不能在外部使用)。

在.m 文件中,声明一个文件全局变量:

static int currentID = 1;

然后在 init 例程中引用:

- (id) init
{
self = [super init];
if (self != nil) {
_myID = currentID++; // not thread safe
}
return self;
}

或者如果它需要在其他时间进行更改(例如在 openConnection 方法中) ,那么在那里增加它。请记住,它不是线程安全的,如果可能存在任何线程问题,您将需要进行同步(或者更好的方法是使用原子添加)。

问题描述 :

  1. 您希望 ClassA 有一个 ClassB 类变量。
  2. 您正在使用 Objective-C 作为编程语言。
  3. Objective-C 不像 C + + 那样支持类变量。

一个选择 :

使用 Objective-C 特性模拟类变量的行为

  1. 在 classA.m 中声明/定义一个静态变量,这样它只能被 classA 方法访问(以及所有放在 classA.m 中的内容)。

  2. 用 ClassB 的实例覆盖 NSObject initialize 类方法,只初始化静态变量一次。

  3. 您可能想知道,为什么要覆盖 NSObject initialize 方法。关于这个方法的苹果文档给出了答案: “运行时仅仅在类或者从它继承的任何类从程序中发送第一条消息之前一次向程序中的每个类发送初始化。(因此,如果不使用该类,则可能永远不会调用该方法。)”.

  4. 可以在任何 ClassA 类/实例方法中随意使用静态变量。

代码示例 :

文件: classA.m

static ClassB *classVariableName = nil;


@implementation ClassA


...
 

+(void) initialize
{
if (! classVariableName)
classVariableName = [[ClassB alloc] init];
}


+(void) classMethodName
{
[classVariableName doSomething];
}


-(void) instanceMethodName
{
[classVariableName doSomething];
}


...


@end

参考文献 :

  1. 解释了比较 Objective-C 和 C + + 方法的类变量

从 Xcode 8开始,您可以在 Obj-C 中定义类属性。这是为了与 Swift 的静态属性进行互操作而添加的。

Objective-C 现在支持与 Swift 类型属性互操作的类属性。它们被声明为:@property (class) NSString * somStringProperty; 。它们永远不会被合成。(23891898)

这里有一个例子

@interface YourClass : NSObject


@property (class, nonatomic, assign) NSInteger currentId;


@end


@implementation YourClass


static NSInteger _currentId = 0;


+ (NSInteger)currentId {
return _currentId;
}


+ (void)setCurrentId:(NSInteger)newValue {
_currentId = newValue;
}


@end

然后你可以这样进入:

YourClass.currentId = 1;
val = YourClass.currentId;

下面是一个非常有趣的 解释性职位,我用它作为参考来编辑这个老答案。


2011年答案: (不要用这个,太可怕了)

如果你真的不想声明一个全局变量,还有另外一个选项,可能不是很正统: ——) ,但是可以... 你可以像这样声明一个“ get & set”方法,里面有一个静态变量:

+ (NSString*)testHolder:(NSString*)_test {
static NSString *test;


if(_test != nil) {
if(test != nil)
[test release];
test = [_test retain];
}


// if(test == nil)
//     test = @"Initialize the var here if you need to";


return test;
}

所以,如果你需要得到这个值,只需要调用:

NSString *testVal = [MyClass testHolder:nil]

然后,当你想设置它的时候:

[MyClass testHolder:testVal]

如果希望将这个伪 static-var 设置为 nil,可以将 testHolder声明为:

+ (NSString*)testHolderSet:(BOOL)shouldSet newValue:(NSString*)_test {
static NSString *test;


if(shouldSet) {
if(test != nil)
[test release];
test = [_test retain];
}


return test;
}

还有两种方法:

+ (NSString*)test {
return [MyClass testHolderSet:NO newValue:nil];
}


+ (void)setTest:(NSString*)_test {
[MyClass testHolderSet:YES newValue:_test];
}

希望能帮上忙,祝你好运。

这里有一个选择:

+(int)getId{
static int id;
//Do anything you need to update the ID here
return id;
}

注意,这个方法将是唯一访问 id 的方法,因此您必须在此代码中以某种方式更新它。

您可以将类重命名为 classA.mm 并在其中添加 C + + 特性。

(严格地说,这不是问题的答案,但是根据我的经验,在寻找类变量时可能会有用)

类方法通常可以扮演类变量在其他语言中扮演的许多角色(例如,在测试期间更改配置) :

@interface MyCls: NSObject
+ (NSString*)theNameThing;
- (void)doTheThing;
@end
@implementation
+ (NSString*)theNameThing { return @"Something general"; }
- (void)doTheThing {
[SomeResource changeSomething:[self.class theNameThing]];
}
@end


@interface MySpecialCase: MyCls
@end
@implementation
+ (NSString*)theNameThing { return @"Something specific"; }
@end

现在,类 MyCls的对象在调用 doTheThing:时使用字符串 @"Something general"调用 Resource:changeSomething:,但是从 MySpecialCase派生的对象使用字符串 @"Something specific"调用 Resource:changeSomething:

另一种可能性是有一个小的 NSNumber子类单例。