目标C静态类级变量

时间:2021-09-22 00:14:51

I have a class Film, each of which stores a unique ID. In C#, Java etc I can define a static int currentID and each time i set the ID i can increase the currentID and the change occurs at the class level not object level. Can this be done in Objective C? I've found it very hard to find an answer for this.

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

9 个解决方案

#1


155  

Issue Description:

问题描述:

  1. You want your ClassA to have a ClassB class variable.
  2. 你希望你的ClassA有一个ClassB类变量。
  3. You are using Objective-C as programming language.
  4. 你使用Objective-C作为编程语言。
  5. Objective-C does not support class variables as C++ does.
  6. Objective-C不像c++那样支持类变量。

One Alternative:

另一个选择:

Simulate a class variable behavior using Objective-C features

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

  1. Declare/Define an static variable within the classA.m so it will be only accessible for the classA methods (and everything you put inside classA.m).

    在classA中声明/定义一个静态变量。因此,只有classA方法(以及您在课堂上输入的所有东西)才能访问它。

  2. Overwrite the NSObject initialize class method to initialize just once the static variable with an instance of ClassB.

    覆盖NSObject初始化类方法,只初始化带有ClassB实例的静态变量一次。

  3. You will be wondering, why should I overwrite the NSObject initialize method. Apple documentation about this method has the answer: "The runtime sends initialize to each class in a program exactly one time just before the class, or any class that inherits from it, is sent its first message from within the program. (Thus the method may never be invoked if the class is not used.)".

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

  4. Feel free to use the static variable within any ClassA class/instance method.

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

Code sample:

代码示例:

file: classA.m

文件: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

References:

引用:

  1. Class variables explained comparing Objective-C and C++ approaches
  2. 类变量解释了比较Objective-C和c++方法

#2


28  

On your .m file, you can declare a variable as static:

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

static ClassName *variableName = nil;

Then you can initialize it on your +(void)initialize method.

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

Please note that this is a plain C static variable and is not static in the sense Java or C# consider it, but will yield similar results.

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

#3


27  

As of Xcode 8, you can define class properties in Obj-C. This has been added to interoperate with Swift's static properties.

从Xcode 8开始,您可以在object - c中定义类属性。这被添加到与Swift的静态属性的互操作中。

Objective-C now supports class properties, which interoperate with Swift type properties. They are declared as: @property (class) NSString *someStringProperty;. They are never synthesized. (23891898)

Objective-C现在支持类属性,与Swift类型属性交互。它们被声明为:@property(类)NSString *someStringProperty;他们从不合成。(23891898)

Here is an example

这是一个例子

@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

Then you can access it like this:

然后你可以这样访问它:

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

Here is a very interesting explanatory post I used as a reference to edit this old answer.

这里有一个非常有趣的解释性文章,我用它作为参考来编辑这个旧答案。


2011 Answer: (don't use this, it's terrible)

2011年的回答:(不要用这个,太糟糕了)

If you really really don't want to declare a global variable, there another option, maybe not very orthodox :-), but works... You can declare a "get&set" method like this, with an static variable inside:

如果你真的不想声明一个全局变量,还有另外一个选项,可能不是很正统:-),但是可以……您可以像这样声明一个“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;
}

So, if you need to get the value, just call:

因此,如果需要获取值,只需调用:

NSString *testVal = [MyClass testHolder:nil]

And then, when you want to set it:

然后,当你想设置它时

[MyClass testHolder:testVal]

In the case you want to be able to set this pseudo-static-var to nil, you can declare testHolder as this:

如果你想把这个伪静态变量设置为nil,你可以把它声明为:

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

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

    return test;
}

And two handy methods:

和两个方便的方法:

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

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

Hope it helps! Good luck.

希望它可以帮助!祝你好运。

#4


16  

In your .m file, declare a file global variable:

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

static int currentID = 1;

then in your init routine, refernce that:

然后在init例程中,引用:

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

or if it needs to change at some other time (eg in your openConnection method), then increment it there. Remember it is not thread safe as is, you'll need to do syncronization (or better yet, use an atomic add) if there may be any threading issues.

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

#5


11  

As pgb said, there are no "class variables," only "instance variables." The objective-c way of doing class variables is a static global variable inside the .m file of the class. The "static" ensures that the variable can not be used outside of that file (i.e. it can't be extern).

正如pgb所说,没有“类变量”,只有“实例变量”。处理类变量的objective-c方法是类的.m文件中的一个静态全局变量。“静态”确保变量不能在该文件之外使用(即不能是extern)。

#6


3  

Here would be an option:

这里有一个选项:

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

Note that this method will be the only method to access id, so you will have to update it somehow in this code.

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

#7


2  

(Strictly speaking not an answer to the question, but in my experience likely to be useful when looking for class variables)

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

A class method can often play many of the roles a class variable would in other languages (e.g. changed configuration during tests):

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

@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

Now, an object of class MyCls calls Resource:changeSomething: with the string @"Something general" upon a call to doTheThing:, but an object derived from MySpecialCase with the string @"Something specific".

现在,MyCls类的一个对象调用Resource:changeSomething:在调用doTheThing时,字符串@“Something general”,但是一个来自MySpecialCase的对象,字符串@“Something specific”。

#8


0  

u can rename the class as classA.mm and add C++ features in it.

可以将类重命名为classA。并在其中添加c++特性。

#9


0  

Another possibility would be to have a little NSNumber subclass singleton.

另一种可能是有一个小的NSNumber子类singleton。

#1


155  

Issue Description:

问题描述:

  1. You want your ClassA to have a ClassB class variable.
  2. 你希望你的ClassA有一个ClassB类变量。
  3. You are using Objective-C as programming language.
  4. 你使用Objective-C作为编程语言。
  5. Objective-C does not support class variables as C++ does.
  6. Objective-C不像c++那样支持类变量。

One Alternative:

另一个选择:

Simulate a class variable behavior using Objective-C features

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

  1. Declare/Define an static variable within the classA.m so it will be only accessible for the classA methods (and everything you put inside classA.m).

    在classA中声明/定义一个静态变量。因此,只有classA方法(以及您在课堂上输入的所有东西)才能访问它。

  2. Overwrite the NSObject initialize class method to initialize just once the static variable with an instance of ClassB.

    覆盖NSObject初始化类方法,只初始化带有ClassB实例的静态变量一次。

  3. You will be wondering, why should I overwrite the NSObject initialize method. Apple documentation about this method has the answer: "The runtime sends initialize to each class in a program exactly one time just before the class, or any class that inherits from it, is sent its first message from within the program. (Thus the method may never be invoked if the class is not used.)".

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

  4. Feel free to use the static variable within any ClassA class/instance method.

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

Code sample:

代码示例:

file: classA.m

文件: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

References:

引用:

  1. Class variables explained comparing Objective-C and C++ approaches
  2. 类变量解释了比较Objective-C和c++方法

#2


28  

On your .m file, you can declare a variable as static:

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

static ClassName *variableName = nil;

Then you can initialize it on your +(void)initialize method.

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

Please note that this is a plain C static variable and is not static in the sense Java or C# consider it, but will yield similar results.

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

#3


27  

As of Xcode 8, you can define class properties in Obj-C. This has been added to interoperate with Swift's static properties.

从Xcode 8开始,您可以在object - c中定义类属性。这被添加到与Swift的静态属性的互操作中。

Objective-C now supports class properties, which interoperate with Swift type properties. They are declared as: @property (class) NSString *someStringProperty;. They are never synthesized. (23891898)

Objective-C现在支持类属性,与Swift类型属性交互。它们被声明为:@property(类)NSString *someStringProperty;他们从不合成。(23891898)

Here is an example

这是一个例子

@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

Then you can access it like this:

然后你可以这样访问它:

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

Here is a very interesting explanatory post I used as a reference to edit this old answer.

这里有一个非常有趣的解释性文章,我用它作为参考来编辑这个旧答案。


2011 Answer: (don't use this, it's terrible)

2011年的回答:(不要用这个,太糟糕了)

If you really really don't want to declare a global variable, there another option, maybe not very orthodox :-), but works... You can declare a "get&set" method like this, with an static variable inside:

如果你真的不想声明一个全局变量,还有另外一个选项,可能不是很正统:-),但是可以……您可以像这样声明一个“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;
}

So, if you need to get the value, just call:

因此,如果需要获取值,只需调用:

NSString *testVal = [MyClass testHolder:nil]

And then, when you want to set it:

然后,当你想设置它时

[MyClass testHolder:testVal]

In the case you want to be able to set this pseudo-static-var to nil, you can declare testHolder as this:

如果你想把这个伪静态变量设置为nil,你可以把它声明为:

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

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

    return test;
}

And two handy methods:

和两个方便的方法:

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

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

Hope it helps! Good luck.

希望它可以帮助!祝你好运。

#4


16  

In your .m file, declare a file global variable:

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

static int currentID = 1;

then in your init routine, refernce that:

然后在init例程中,引用:

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

or if it needs to change at some other time (eg in your openConnection method), then increment it there. Remember it is not thread safe as is, you'll need to do syncronization (or better yet, use an atomic add) if there may be any threading issues.

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

#5


11  

As pgb said, there are no "class variables," only "instance variables." The objective-c way of doing class variables is a static global variable inside the .m file of the class. The "static" ensures that the variable can not be used outside of that file (i.e. it can't be extern).

正如pgb所说,没有“类变量”,只有“实例变量”。处理类变量的objective-c方法是类的.m文件中的一个静态全局变量。“静态”确保变量不能在该文件之外使用(即不能是extern)。

#6


3  

Here would be an option:

这里有一个选项:

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

Note that this method will be the only method to access id, so you will have to update it somehow in this code.

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

#7


2  

(Strictly speaking not an answer to the question, but in my experience likely to be useful when looking for class variables)

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

A class method can often play many of the roles a class variable would in other languages (e.g. changed configuration during tests):

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

@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

Now, an object of class MyCls calls Resource:changeSomething: with the string @"Something general" upon a call to doTheThing:, but an object derived from MySpecialCase with the string @"Something specific".

现在,MyCls类的一个对象调用Resource:changeSomething:在调用doTheThing时,字符串@“Something general”,但是一个来自MySpecialCase的对象,字符串@“Something specific”。

#8


0  

u can rename the class as classA.mm and add C++ features in it.

可以将类重命名为classA。并在其中添加c++特性。

#9


0  

Another possibility would be to have a little NSNumber subclass singleton.

另一种可能是有一个小的NSNumber子类singleton。