Objective-C 静态类级别变量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1063229/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 21:48:57  来源:igfitidea点击:

Objective-C Static Class Level variables

objective-cvariablesstatic

提问by Albaregar

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.

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

回答by Albaregar

Issue Description:

问题描述

  1. You want your ClassA to have a ClassB class variable.
  2. You are using Objective-C as programming language.
  3. Objective-C does not support class variables as C++ does.
  1. 您希望 ClassA 具有 ClassB 类变量。
  2. 您正在使用 Objective-C 作为编程语言。
  3. 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).

  2. Overwrite the NSObject initialize class method to initialize just once the static variable with an instance of 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.)".

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

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

  2. 覆盖 NSObject 初始化类方法以使用 ClassB 的实例仅初始化一次静态变量。

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

  4. 随意在任何 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
  1. 类变量解释比较 Objective-C 和 C++ 方法

回答by Gonzalo Larralde

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 开始,您可以在 Obj-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 (class) 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 postI 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 testHolderas this:

如果您希望能够将此伪静态变量设置为 nil,您可以声明testHolder如下:

+ (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.

希望能帮助到你!祝你好运。

回答by pgb

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

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

static ClassName *variableName = nil;

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

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

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# 考虑的意义上不是静态的,但会产生类似的结果。

回答by Peter N Lewis

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 方法中),然后在那里增加它。请记住,它不是线程安全的,如果可能存在任何线程问题,您需要进行同步(或者更好的是,使用原子添加)。

回答by Tom Dalling

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)。

回答by Anonymous

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 的唯一方法,因此您必须在此代码中以某种方式更新它。

回答by Jacob Oscarson

(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 MyClscalls Resource:changeSomething:with the string @"Something general"upon a call to doTheThing:, but an object derived from MySpecialCasewith the string @"Something specific".

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

回答by Rudolf Adamkovi?

Another possibility would be to have a little NSNumbersubclass singleton.

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

回答by rd_

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

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