Objective C静态类级变量

时间:2009-06-30 11:45:47

标签: objective-c variables static

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

9 个答案:

答案 0 :(得分:157)

问题说明

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

    使用Objective-C功能模拟类变量行为

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

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

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

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

    5. 代码示例

      file: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. Class variables explained comparing Objective-C and C++ approaches

答案 1 :(得分:30)

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

  

Objective-C现在支持类属性,它与Swift类型属性互操作。它们被声明为:@property(class)NSString * someStringProperty;。它们永远不会合成。 (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;

这是一个非常有趣的explanatory post我用作编辑这个旧答案的参考。


2011答案:(不要使用它,这太可怕了)

如果你真的真的不想宣布一个全局变量,还有另一种选择,也许不是非常正统:-),但是有效...你可以用静态声明一个“get&amp; 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]

如果您希望能够将此伪静态变量设置为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];
}

希望它有所帮助!祝你好运。

答案 2 :(得分:29)

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

static ClassName *variableName = nil;

然后,您可以使用+(void)initialize方法对其进行初始化。

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

答案 3 :(得分:16)

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

static int currentID = 1;

然后在你的init例程中,参考:

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

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

答案 4 :(得分:11)

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

答案 5 :(得分:3)

这是一个选项:

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

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

答案 6 :(得分:2)

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

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

@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的对象在调用Resource:changeSomething:时调用@"Something general"字符串doTheThing:,但是从MySpecialCase派生的对象调用@"Something specific"字符串{{1}}。

答案 7 :(得分:0)

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

答案 8 :(得分:0)

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